--- a/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
5ac6287ec71aafe021cc839d8bc828108d23aaba jdk-9+95
139f19d70350238e15e107945cea75082b6380b3 jdk-9+96
4edcff1b9a8875eb6380a2165dfec599e8e3f7c0 jdk-9+97
+d00ad2d9049ac60815f70bff445e95df85648bd2 jdk-9+98
+f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99
--- a/.hgtags-top-repo Wed Jan 06 09:39:55 2016 -0500
+++ b/.hgtags-top-repo Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
12a6fb4f070f8ca8fbca219ab9abf5da8908b317 jdk-9+95
5582a79892596169ebddb3e2c2aa44939e4e3f40 jdk-9+96
75c3897541ecb52ee16d001ea605b12971df7303 jdk-9+97
+48987460c7d49a29013963ee44d090194396bb61 jdk-9+98
+7c0577bea4c65d69c5bef67023a89d2efa4fb2f7 jdk-9+99
--- a/README Wed Jan 06 09:39:55 2016 -0500
+++ b/README Wed Jan 06 14:54:24 2016 +0000
@@ -6,7 +6,7 @@
The root repository can be obtained with something like:
hg clone http://hg.openjdk.java.net/jdk9/jdk9 openjdk9
-
+
You can run the get_source.sh script located in the root repository to get
the other needed repositories:
cd openjdk9 && sh ./get_source.sh
@@ -17,7 +17,7 @@
See http://openjdk.java.net/ for more information about OpenJDK.
Simple Build Instructions:
-
+
0. Get the necessary system software/packages installed on your system, see
http://hg.openjdk.java.net/jdk9/jdk9/raw-file/tip/README-builds.html
@@ -28,10 +28,10 @@
2. Configure the build:
bash ./configure
-
+
3. Build the OpenJDK:
make all
- The resulting JDK image should be found in build/*/images/j2sdk-image
+ The resulting JDK image should be found in build/*/images/jdk
where make is GNU make 3.81 or newer, /usr/bin/make on Linux usually
is 3.81 or newer. Note that on Solaris, GNU make is called "gmake".
--- a/README-builds.html Wed Jan 06 09:39:55 2016 -0500
+++ b/README-builds.html Wed Jan 06 14:54:24 2016 +0000
@@ -250,9 +250,7 @@
</ul></li>
<li><p><strong>Mac OS X</strong></p>
-<p>Install <a href="https://developer.apple.com/xcode/">XCode 4.5.2</a> and also
-install the "Command line tools" found under the preferences pane
-"Downloads"</p></li>
+<p>Install <a href="https://developer.apple.com/xcode/">XCode 6.3</a></p></li>
</ul>
<p><a name="linux"></a></p>
@@ -279,39 +277,67 @@
<h5>Studio Compilers</h5>
<p>At a minimum, the <a href="http://www.oracle.com/
-technetwork/server-storage/solarisstudio/downloads/index.htm">Studio 12 Update 1 Compilers</a> (containing
-version 5.10 of the C and C++ compilers) is required, including specific
+technetwork/server-storage/solarisstudio/downloads/index.htm">Studio 12 Update 4 Compilers</a> (containing
+version 5.13 of the C and C++ compilers) is required, including specific
patches.</p>
-<p>The Solaris SPARC patch list is:</p>
+<p>The Solaris Studio installation should contain at least these packages:</p>
-<ul>
-<li>118683-05: SunOS 5.10: Patch for profiling libraries and assembler</li>
-<li>119963-21: SunOS 5.10: Shared library patch for C++</li>
-<li>120753-08: SunOS 5.10: Microtasking libraries (libmtsk) patch</li>
-<li>128228-09: Sun Studio 12 Update 1: Patch for Sun C++ Compiler</li>
-<li>141860-03: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
-C++ F77 F95</li>
-<li>141861-05: Sun Studio 12 Update 1: Patch for Sun C Compiler</li>
-<li>142371-01: Sun Studio 12.1 Update 1: Patch for dbx</li>
-<li>143384-02: Sun Studio 12 Update 1: Patch for debuginfo handling</li>
-<li>143385-02: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
-C++ F77 F95</li>
-<li>142369-01: Sun Studio 12.1: Patch for Performance Analyzer Tools</li>
-</ul>
+<blockquote>
+ <p><table border="1">
+ <thead>
+ <tr>
+ <td><strong>Package</strong></td>
+ <td><strong>Version</strong></td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>developer/solarisstudio-124/backend</td>
+ <td>12.4-1.0.6.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/c++</td>
+ <td>12.4-1.0.10.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/cc</td>
+ <td>12.4-1.0.4.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/c++-libs</td>
+ <td>12.4-1.0.10.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/math-libs</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/studio-gccrt</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-common</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-ja</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-legal</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-zhCN</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ </tbody>
+ </table></p>
+</blockquote>
-<p>The Solaris X86 patch list is:</p>
-
-<ul>
-<li>119961-07: SunOS 5.10_x86, x64, Patch for profiling libraries and assembler</li>
-<li>119964-21: SunOS 5.10_x86: Shared library patch for C++_x86</li>
-<li>120754-08: SunOS 5.10_x86: Microtasking libraries (libmtsk) patch</li>
-<li>141858-06: Sun Studio 12 Update 1_x86: Sun Compiler Common patch for x86
-backend</li>
-<li>128229-09: Sun Studio 12 Update 1_x86: Patch for C++ Compiler</li>
-<li>142363-05: Sun Studio 12 Update 1_x86: Patch for C Compiler</li>
-<li>142368-01: Sun Studio 12.1_x86: Patch for Performance Analyzer Tools</li>
-</ul>
+<p>In particular backend 12.4-1.0.6.0 contains a critical patch for the sparc
+version.</p>
<p>Place the <code>bin</code> directory in <code>PATH</code>.</p>
@@ -1144,10 +1170,6 @@
<p>With Linux, it was just a matter of picking a stable distribution that is a
good representative for Linux in general.</p>
-<p><strong>NOTE: We expect a change here from Fedora 9 to something else, but it has not
-been completely determined yet, possibly Ubuntu 12.04 X64, unbiased community
-feedback would be welcome on what a good choice would be here.</strong></p>
-
<p>It is understood that most developers will NOT be using these specific
versions, and in fact creating these specific versions may be difficult due to
the age of some of this software. It is expected that developers are more often
@@ -1176,7 +1198,7 @@
<tr>
<td>Linux X86 (32-bit) and X64 (64-bit)</td>
<td>Oracle Enterprise Linux 6.4</td>
- <td>gcc 4.8.2 </td>
+ <td>gcc 4.9.2 </td>
<td>JDK 8</td>
<td>2 or more</td>
<td>1 GB</td>
@@ -1184,8 +1206,8 @@
</tr>
<tr>
<td>Solaris SPARCV9 (64-bit)</td>
- <td>Solaris 10 Update 10</td>
- <td>Studio 12 Update 3 + patches</td>
+ <td>Solaris 11 Update 1</td>
+ <td>Studio 12 Update 4 + patches</td>
<td>JDK 8</td>
<td>4 or more</td>
<td>4 GB</td>
@@ -1193,8 +1215,8 @@
</tr>
<tr>
<td>Solaris X64 (64-bit)</td>
- <td>Solaris 10 Update 10</td>
- <td>Studio 12 Update 3 + patches</td>
+ <td>Solaris 11 Update 1</td>
+ <td>Studio 12 Update 4 + patches</td>
<td>JDK 8</td>
<td>4 or more</td>
<td>4 GB</td>
@@ -1221,7 +1243,7 @@
<tr>
<td>Mac OS X X64 (64-bit)</td>
<td>Mac OS X 10.9 "Mavericks"</td>
- <td>XCode 5.1.1 or newer</td>
+ <td>Xcode 6.3 or newer</td>
<td>JDK 8</td>
<td>2 or more</td>
<td>4 GB</td>
--- a/README-builds.md Wed Jan 06 09:39:55 2016 -0500
+++ b/README-builds.md Wed Jan 06 14:54:24 2016 +0000
@@ -215,9 +215,7 @@
* **Mac OS X**
- Install [XCode 4.5.2](https://developer.apple.com/xcode/) and also
- install the "Command line tools" found under the preferences pane
- "Downloads"
+ Install [XCode 6.3](https://developer.apple.com/xcode/)
<a name="linux"></a>
#### Linux
@@ -239,36 +237,66 @@
<a name="studio"></a>
##### Studio Compilers
-At a minimum, the [Studio 12 Update 1 Compilers](http://www.oracle.com/
+At a minimum, the [Studio 12 Update 4 Compilers](http://www.oracle.com/
technetwork/server-storage/solarisstudio/downloads/index.htm) (containing
-version 5.10 of the C and C++ compilers) is required, including specific
+version 5.13 of the C and C++ compilers) is required, including specific
patches.
-The Solaris SPARC patch list is:
+The Solaris Studio installation should contain at least these packages:
- * 118683-05: SunOS 5.10: Patch for profiling libraries and assembler
- * 119963-21: SunOS 5.10: Shared library patch for C++
- * 120753-08: SunOS 5.10: Microtasking libraries (libmtsk) patch
- * 128228-09: Sun Studio 12 Update 1: Patch for Sun C++ Compiler
- * 141860-03: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
- C++ F77 F95
- * 141861-05: Sun Studio 12 Update 1: Patch for Sun C Compiler
- * 142371-01: Sun Studio 12.1 Update 1: Patch for dbx
- * 143384-02: Sun Studio 12 Update 1: Patch for debuginfo handling
- * 143385-02: Sun Studio 12 Update 1: Patch for Compiler Common patch for Sun C
- C++ F77 F95
- * 142369-01: Sun Studio 12.1: Patch for Performance Analyzer Tools
+> <table border="1">
+ <thead>
+ <tr>
+ <td>**Package**</td>
+ <td>**Version**</td>
+ </tr>
+ </thead>
+ <tbody>
+ <tr>
+ <td>developer/solarisstudio-124/backend</td>
+ <td>12.4-1.0.6.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/c++</td>
+ <td>12.4-1.0.10.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/cc</td>
+ <td>12.4-1.0.4.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/c++-libs</td>
+ <td>12.4-1.0.10.0</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/math-libs</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/library/studio-gccrt</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-common</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-ja</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-legal</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ <tr>
+ <td>developer/solarisstudio-124/studio-zhCN</td>
+ <td>12.4-1.0.0.1</td>
+ </tr>
+ </tbody>
+ </table>
-The Solaris X86 patch list is:
-
- * 119961-07: SunOS 5.10_x86, x64, Patch for profiling libraries and assembler
- * 119964-21: SunOS 5.10_x86: Shared library patch for C++\_x86
- * 120754-08: SunOS 5.10_x86: Microtasking libraries (libmtsk) patch
- * 141858-06: Sun Studio 12 Update 1_x86: Sun Compiler Common patch for x86
- backend
- * 128229-09: Sun Studio 12 Update 1_x86: Patch for C++ Compiler
- * 142363-05: Sun Studio 12 Update 1_x86: Patch for C Compiler
- * 142368-01: Sun Studio 12.1_x86: Patch for Performance Analyzer Tools
+In particular backend 12.4-1.0.6.0 contains a critical patch for the sparc
+version.
Place the `bin` directory in `PATH`.
@@ -1044,10 +1072,6 @@
With Linux, it was just a matter of picking a stable distribution that is a
good representative for Linux in general.
-**NOTE: We expect a change here from Fedora 9 to something else, but it has not
-been completely determined yet, possibly Ubuntu 12.04 X64, unbiased community
-feedback would be welcome on what a good choice would be here.**
-
It is understood that most developers will NOT be using these specific
versions, and in fact creating these specific versions may be difficult due to
the age of some of this software. It is expected that developers are more often
@@ -1075,7 +1099,7 @@
<tr>
<td>Linux X86 (32-bit) and X64 (64-bit)</td>
<td>Oracle Enterprise Linux 6.4</td>
- <td>gcc 4.8.2 </td>
+ <td>gcc 4.9.2 </td>
<td>JDK 8</td>
<td>2 or more</td>
<td>1 GB</td>
@@ -1083,8 +1107,8 @@
</tr>
<tr>
<td>Solaris SPARCV9 (64-bit)</td>
- <td>Solaris 10 Update 10</td>
- <td>Studio 12 Update 3 + patches</td>
+ <td>Solaris 11 Update 1</td>
+ <td>Studio 12 Update 4 + patches</td>
<td>JDK 8</td>
<td>4 or more</td>
<td>4 GB</td>
@@ -1092,8 +1116,8 @@
</tr>
<tr>
<td>Solaris X64 (64-bit)</td>
- <td>Solaris 10 Update 10</td>
- <td>Studio 12 Update 3 + patches</td>
+ <td>Solaris 11 Update 1</td>
+ <td>Studio 12 Update 4 + patches</td>
<td>JDK 8</td>
<td>4 or more</td>
<td>4 GB</td>
@@ -1120,7 +1144,7 @@
<tr>
<td>Mac OS X X64 (64-bit)</td>
<td>Mac OS X 10.9 "Mavericks"</td>
- <td>XCode 5.1.1 or newer</td>
+ <td>Xcode 6.3 or newer</td>
<td>JDK 8</td>
<td>2 or more</td>
<td>4 GB</td>
--- a/common/autoconf/build-performance.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/build-performance.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -149,6 +149,19 @@
AC_SUBST(JOBS)
])
+AC_DEFUN_ONCE([BPERF_SETUP_TEST_JOBS],
+[
+ # The number of test jobs will be chosen automatically if TEST_JOBS is 0
+ AC_ARG_WITH(test-jobs, [AS_HELP_STRING([--with-test-jobs],
+ [number of parallel tests jobs to run @<:@based on build jobs@:>@])])
+ if test "x$with_test_jobs" = x; then
+ TEST_JOBS=0
+ else
+ TEST_JOBS=$with_test_jobs
+ fi
+ AC_SUBST(TEST_JOBS)
+])
+
AC_DEFUN([BPERF_SETUP_CCACHE],
[
AC_ARG_ENABLE([ccache],
--- a/common/autoconf/configure.ac Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/configure.ac Wed Jan 06 14:54:24 2016 +0000
@@ -44,6 +44,7 @@
m4_include([build-performance.m4])
m4_include([flags.m4])
m4_include([help.m4])
+m4_include([hotspot.m4])
m4_include([jdk-options.m4])
m4_include([jdk-version.m4])
m4_include([libraries.m4])
@@ -94,9 +95,10 @@
# These are needed to be able to create a configuration name (and thus the output directory)
JDKOPT_SETUP_JDK_VARIANT
-JDKOPT_SETUP_JVM_INTERPRETER
-JDKOPT_SETUP_JVM_VARIANTS
+HOTSPOT_SETUP_JVM_INTERPRETER
+HOTSPOT_SETUP_JVM_VARIANTS
JDKOPT_SETUP_DEBUG_LEVEL
+HOTSPOT_SETUP_DEBUG_LEVEL
# With basic setup done, call the custom early hook.
CUSTOM_EARLY_HOOK
@@ -132,6 +134,7 @@
# We need build & target for this.
JDKOPT_SETUP_JDK_OPTIONS
+HOTSPOT_SETUP_HOTSPOT_OPTIONS
JDKVER_SETUP_JDK_VERSION_NUMBERS
###############################################################################
@@ -220,7 +223,7 @@
#
###############################################################################
-JDKOPT_SETUP_BUILD_TWEAKS
+HOTSPOT_SETUP_BUILD_TWEAKS
JDKOPT_DETECT_INTREE_EC
###############################################################################
@@ -233,6 +236,7 @@
BPERF_SETUP_BUILD_CORES
BPERF_SETUP_BUILD_MEMORY
BPERF_SETUP_BUILD_JOBS
+BPERF_SETUP_TEST_JOBS
# Setup arguments for the boot jdk (after cores and memory have been setup)
BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS
--- a/common/autoconf/flags.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/flags.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -120,13 +120,17 @@
AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS],
[
- # Option used to tell the compiler whether to create 32- or 64-bit executables
+ # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
+ # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
+ COMPILER_COMMAND_FILE_FLAG="-f"
else
COMPILER_TARGET_BITS_FLAG="-m"
+ COMPILER_COMMAND_FILE_FLAG="@"
fi
AC_SUBST(COMPILER_TARGET_BITS_FLAG)
+ AC_SUBST(COMPILER_COMMAND_FILE_FLAG)
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
@@ -226,37 +230,38 @@
else
SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
fi
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1'
+ SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1'
SET_SHARED_LIBRARY_MAPFILE=''
else
# Default works for linux, might work on other platforms as well.
SHARED_LIBRARY_FLAGS='-shared'
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN[$]1'
- SET_SHARED_LIBRARY_ORIGIN="-Xlinker -z -Xlinker origin $SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -soname=[$]1'
- SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=[$]1'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1'
+ SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
+ SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
+ SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
fi
elif test "x$TOOLCHAIN_TYPE" = xclang; then
- PICFLAG=''
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
# Linking is different on MacOSX
+ PICFLAG=''
SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/[$]1'
+ SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/[$]1'
SET_SHARED_LIBRARY_MAPFILE=''
else
# Default works for linux, might work on other platforms as well.
+ PICFLAG='-fPIC'
SHARED_LIBRARY_FLAGS='-shared'
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN[$]1'
- SET_SHARED_LIBRARY_ORIGIN="-Xlinker -z -Xlinker origin $SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -soname=[$]1'
- SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=[$]1'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1'
+ SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
+ SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
+ SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
PICFLAG="-KPIC"
@@ -265,7 +270,7 @@
SHARED_LIBRARY_FLAGS="-G"
SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN[$]1'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME=''
+ SET_SHARED_LIBRARY_NAME='-h [$]1'
SET_SHARED_LIBRARY_MAPFILE='-M[$]1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
PICFLAG="-qpic=large"
@@ -280,7 +285,7 @@
PICFLAG=""
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-LD"
+ SHARED_LIBRARY_FLAGS="-dll"
SET_EXECUTABLE_ORIGIN=''
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -293,6 +298,7 @@
AC_SUBST(SET_SHARED_LIBRARY_ORIGIN)
AC_SUBST(SET_SHARED_LIBRARY_NAME)
AC_SUBST(SET_SHARED_LIBRARY_MAPFILE)
+ AC_SUBST(SHARED_LIBRARY_FLAGS)
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__"
@@ -573,6 +579,25 @@
CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
;;
esac
+ elif test "x$TOOLCHAIN_TYPE" = xclang; then
+ if test "x$OPENJDK_TARGET_OS" = xlinux; then
+ if test "x$OPENJDK_TARGET_CPU" = xx86; then
+ # Force compatibility with i586 on 32 bit intel platforms.
+ COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586"
+ fi
+ COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \
+ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
+ case $OPENJDK_TARGET_CPU_ARCH in
+ ppc )
+ # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing
+ CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
+ ;;
+ * )
+ COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer"
+ CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
+ ;;
+ esac
+ fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS"
if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then
@@ -748,17 +773,17 @@
# If this is a --hash-style=gnu system, use --hash-style=both, why?
# We have previously set HAS_GNU_HASH if this is the case
if test -n "$HAS_GNU_HASH"; then
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker --hash-style=both"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,--hash-style=both"
fi
if test "x$OPENJDK_TARGET_OS" = xlinux; then
# And since we now know that the linker is gnu, then add -z defs, to forbid
# undefined symbols in object files.
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -z -Xlinker defs"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,-z,defs"
case $DEBUG_LEVEL in
release )
# tell linker to optimize libraries.
# Should this be supplied to the OSS linker as well?
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -O1"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,-O1"
;;
slowdebug )
if test "x$HAS_LINKER_NOW" = "xtrue"; then
@@ -785,7 +810,7 @@
esac
fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
- LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext"
+ LDFLAGS_JDK="$LDFLAGS_JDK -Wl,-z,defs -xildoff -ztext"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -bexpall -bernotok"
@@ -803,17 +828,19 @@
fi
LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE"
elif test "x$OPENJDK_TARGET_OS" = xlinux; then
- LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Xlinker --allow-shlib-undefined"
+ LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
fi
# Customize LDFLAGS for libs
LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}"
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
- LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -dll -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
+ -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
JDKLIB_LIBS=""
else
- LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS} \
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
-L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
# On some platforms (mac) the linker warns about non existing -L dirs.
--- a/common/autoconf/generated-configure.sh Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/generated-configure.sh Wed Jan 06 14:54:24 2016 +0000
@@ -646,11 +646,11 @@
JAVA_FLAGS_JAVAC
JAVA_FLAGS_BIG
JAVA_FLAGS
+TEST_JOBS
JOBS
MEMORY_SIZE
NUM_CORES
ENABLE_INTREE_EC
-SALIB_NAME
HOTSPOT_MAKE_ARGS
LIBZIP_CAN_USE_MMAP
LIBDL
@@ -729,6 +729,7 @@
CFLAGS_DEBUG_SYMBOLS
CXX_FLAG_DEPS
C_FLAG_DEPS
+SHARED_LIBRARY_FLAGS
SET_SHARED_LIBRARY_MAPFILE
SET_SHARED_LIBRARY_NAME
SET_SHARED_LIBRARY_ORIGIN
@@ -742,6 +743,7 @@
CC_OUT_OPTION
STRIPFLAGS
ARFLAGS
+COMPILER_COMMAND_FILE_FLAG
COMPILER_TARGET_BITS_FLAG
JT_HOME
JTREGEXE
@@ -753,6 +755,7 @@
HOTSPOT_RC
HOTSPOT_MT
BUILD_AS
+BUILD_LDCXX
BUILD_LD
BUILD_AR
BUILD_NM
@@ -799,6 +802,7 @@
PROPER_COMPILER_CC
TOOLCHAIN_PATH_CC
POTENTIAL_CC
+TOOLCHAIN_VERSION
VS_LIB
VS_INCLUDE
VS_PATH
@@ -857,11 +861,11 @@
PRODUCT_SUFFIX
PRODUCT_NAME
LAUNCHER_NAME
+TEST_IN_BUILD
COPYRIGHT_YEAR
COMPRESS_JARS
UNLIMITED_CRYPTO
CACERTS_FILE
-TEST_IN_BUILD
BUILD_HEADLESS
SUPPORT_HEADFUL
SUPPORT_HEADLESS
@@ -910,7 +914,6 @@
JVM_VARIANT_CORE
JVM_VARIANT_ZEROSHARK
JVM_VARIANT_ZERO
-JVM_VARIANT_KERNEL
JVM_VARIANT_MINIMAL1
JVM_VARIANT_CLIENT
JVM_VARIANT_SERVER
@@ -1073,10 +1076,10 @@
with_output_sync
with_default_make_target
enable_headful
-enable_hotspot_test_in_build
with_cacerts_file
enable_unlimited_crypto
with_copyright_year
+enable_hotspot_test_in_build
with_milestone
with_update_version
with_user_release_suffix
@@ -1142,6 +1145,7 @@
with_num_cores
with_memory_size
with_jobs
+with_test_jobs
with_boot_jdk_jvmargs
with_sjavac_server_java
enable_sjavac
@@ -1883,10 +1887,10 @@
--with-debug-level=fastdebug) [disabled]
--disable-headful disable building headful support (graphical UI
support) [enabled]
+ --enable-unlimited-crypto
+ Enable unlimited crypto policy [disabled]
--enable-hotspot-test-in-build
run the Queens test after Hotspot build [disabled]
- --enable-unlimited-crypto
- Enable unlimited crypto policy [disabled]
--enable-static-build enable static library build [disabled]
--disable-warnings-as-errors
do not consider native warnings to be an error
@@ -1923,8 +1927,7 @@
--with-jdk-variant JDK variant to build (normal) [normal]
--with-jvm-interpreter JVM interpreter to build (template, cpp) [template]
--with-jvm-variants JVM variants (separated by commas) to build (server,
- client, minimal1, kernel, zero, zeroshark, core)
- [server]
+ client, minimal1, zero, zeroshark, core) [server]
--with-debug-level set the debug level (release, fastdebug, slowdebug,
optimized (HotSpot build only)) [release]
--with-devkit use this devkit for compilers, tools and resources
@@ -2061,6 +2064,8 @@
--with-memory-size=1024 [probed]
--with-jobs number of parallel jobs to let make run [calculated
based on cores and memory]
+ --with-test-jobs number of parallel tests jobs to run [based on build
+ jobs]
--with-boot-jdk-jvmargs specify JVM arguments to be passed to all java
invocations of boot JDK, overriding the default
values, e.g --with-boot-jdk-jvmargs="-Xmx8G
@@ -3747,7 +3752,7 @@
#
-# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -3785,6 +3790,8 @@
+
+
################################################################################
#
# Optionally enable distributed compilation of native code using icecc/icecream
@@ -3939,7 +3946,11 @@
automatically build the freetype library into '<freetype_src>/lib64' for 64-bit
builds or into '<freetype_src>/lib32' for 32-bit builds.
Afterwards you can always use '--with-freetype-include=<freetype_src>/include'
-and '--with-freetype-lib=<freetype_src>/lib32|64' for other builds."
+and '--with-freetype-lib=<freetype_src>/lib32|64' for other builds.
+
+Alternatively you can unpack the sources like this to use the default directory:
+
+tar --one-top-level=$HOME/freetype --strip-components=1 -xzf freetype-2.5.3.tar.gz"
;;
esac
}
@@ -4037,13 +4048,80 @@
# questions.
#
-
-
-
-
-
-
-
+###############################################################################
+# Check which interpreter of the JVM we want to build.
+# Currently we have:
+# template: Template interpreter (the default)
+# cpp : C++ interpreter
+
+
+###############################################################################
+# Check which variants of the JVM that we want to build.
+# Currently we have:
+# server: normal interpreter and a C2 or tiered C1/C2 compiler
+# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms)
+# minimal1: reduced form of client with optional VM services and features stripped out
+# zero: no machine code interpreter, no compiler
+# zeroshark: zero interpreter and shark/llvm compiler backend
+# core: interpreter only, no compiler (only works on some platforms)
+
+
+
+###############################################################################
+# Setup legacy vars/targets and new vars to deal with different debug levels.
+#
+# release: no debug information, all optimizations, no asserts.
+# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
+# fastdebug: debug information (-g), all optimizations, all asserts
+# slowdebug: debug information (-g), no optimizations, all asserts
+#
+
+
+
+
+
+
+#
+# Copyright (c) 2011, 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.
+#
+
+###############################################################################
+# Check which variant of the JDK that we want to build.
+# Currently we have:
+# normal: standard edition
+# but the custom make system may add other variants
+#
+# Effectively the JDK variant gives a name to a specific set of
+# modules to compile into the JDK.
+
+
+###############################################################################
+# Set the debug level
+# release: no debug information, all optimizations, no asserts.
+# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
+# fastdebug: debug information (-g), all optimizations, all asserts
+# slowdebug: debug information (-g), no optimizations, all asserts
###############################################################################
@@ -4054,8 +4132,6 @@
-
-
###############################################################################
#
# Enable or disable the elliptic curve crypto implementation
@@ -4064,7 +4140,6 @@
-
################################################################################
#
# Gcov coverage data for hotspot
@@ -4078,8 +4153,6 @@
#
-
-
#
# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4728,7 +4801,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1449850507
+DATE_WHEN_GENERATED=1450277321
###############################################################################
#
@@ -15607,17 +15680,6 @@
# These are needed to be able to create a configuration name (and thus the output directory)
- ###############################################################################
- #
- # Check which variant of the JDK that we want to build.
- # Currently we have:
- # normal: standard edition
- # but the custom make system may add other variants
- #
- # Effectively the JDK variant gives a name to a specific set of
- # modules to compile into the JDK. In the future, these modules
- # might even be Jigsaw modules.
- #
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of the JDK to build" >&5
$as_echo_n "checking which variant of the JDK to build... " >&6; }
@@ -15639,14 +15701,6 @@
$as_echo "$JDK_VARIANT" >&6; }
-###############################################################################
-#
-# Check which interpreter of the JVM we want to build.
-# Currently we have:
-# template: Template interpreter (the default)
-# cpp : C++ interpreter
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which interpreter of the JVM to build" >&5
-$as_echo_n "checking which interpreter of the JVM to build... " >&6; }
# Check whether --with-jvm-interpreter was given.
if test "${with_jvm_interpreter+set}" = set; then :
@@ -15654,35 +15708,23 @@
fi
-if test "x$with_jvm_interpreter" = x; then
- with_jvm_interpreter="template"
-fi
-
-JVM_INTERPRETER="$with_jvm_interpreter"
-
-if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then
- as_fn_error $? "The available JVM interpreters are: template, cpp" "$LINENO" 5
-fi
-
-
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jvm_interpreter" >&5
-$as_echo "$with_jvm_interpreter" >&6; }
-
-
-
- ###############################################################################
- #
- # Check which variants of the JVM that we want to build.
- # Currently we have:
- # server: normal interpreter and a tiered C1/C2 compiler
- # client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms)
- # minimal1: reduced form of client with optional VM services and features stripped out
- # kernel: kernel footprint JVM that passes the TCK without major performance problems,
- # ie normal interpreter and C1, only the serial GC, kernel jvmti etc
- # zero: no machine code interpreter, no compiler
- # zeroshark: zero interpreter and shark/llvm compiler backend
-# core: interpreter only, no compiler (only works on some platforms)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking which interpreter of the JVM to build" >&5
+$as_echo_n "checking which interpreter of the JVM to build... " >&6; }
+ if test "x$with_jvm_interpreter" = x; then
+ JVM_INTERPRETER="template"
+ else
+ JVM_INTERPRETER="$with_jvm_interpreter"
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JVM_INTERPRETER" >&5
+$as_echo "$JVM_INTERPRETER" >&6; }
+
+ if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then
+ as_fn_error $? "The available JVM interpreters are: template, cpp" "$LINENO" 5
+ fi
+
+
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which variants of the JVM to build" >&5
$as_echo_n "checking which variants of the JVM to build... " >&6; }
@@ -15697,10 +15739,10 @@
fi
JVM_VARIANTS=",$with_jvm_variants,"
- TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/kernel,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'`
+ TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'`
if test "x$TEST_VARIANTS" != "x,"; then
- as_fn_error $? "The available JVM variants are: server, client, minimal1, kernel, zero, zeroshark, core" "$LINENO" 5
+ as_fn_error $? "The available JVM variants are: server, client, minimal1, zero, zeroshark, core" "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jvm_variants" >&5
$as_echo "$with_jvm_variants" >&6; }
@@ -15708,7 +15750,6 @@
JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'`
JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'`
JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'`
- JVM_VARIANT_KERNEL=`$ECHO "$JVM_VARIANTS" | $SED -e '/,kernel,/!s/.*/false/g' -e '/,kernel,/s/.*/true/g'`
JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'`
JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'`
JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'`
@@ -15718,11 +15759,6 @@
as_fn_error $? "You cannot build a client JVM for a 64-bit machine." "$LINENO" 5
fi
fi
- if test "x$JVM_VARIANT_KERNEL" = xtrue; then
- if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- as_fn_error $? "You cannot build a kernel JVM for a 64-bit machine." "$LINENO" 5
- fi
- fi
if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
as_fn_error $? "You cannot build a minimal JVM for a 64-bit machine." "$LINENO" 5
@@ -15731,13 +15767,16 @@
# Replace the commas with AND for use in the build directory name.
ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'`
- COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/kernel,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
+ COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
if test "x$COUNT_VARIANTS" != "x,1"; then
BUILDING_MULTIPLE_JVM_VARIANTS=yes
else
BUILDING_MULTIPLE_JVM_VARIANTS=no
fi
+ if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then
+ as_fn_error $? "You cannot build multiple variants with zero." "$LINENO" 5
+ fi
@@ -15769,14 +15808,6 @@
- ###############################################################################
- #
- # Set the debug level
- # release: no debug information, all optimizations, no asserts.
- # optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
- # fastdebug: debug information (-g), all optimizations, all asserts
- # slowdebug: debug information (-g), no optimizations, all asserts
- #
DEBUG_LEVEL="release"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking which debug level to use" >&5
$as_echo_n "checking which debug level to use... " >&6; }
@@ -15813,11 +15844,6 @@
fi
- ###############################################################################
- #
- # Setup legacy vars/targets and new vars to deal with different debug levels.
- #
-
case $DEBUG_LEVEL in
release )
VARIANT="OPT"
@@ -15887,10 +15913,6 @@
HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 "
fi
- if test "x$JVM_VARIANT_KERNEL" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}kernel "
- fi
-
if test "x$JVM_VARIANT_ZERO" = xtrue; then
HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero "
fi
@@ -23122,12 +23144,8 @@
# We need build & target for this.
-
- ###############################################################################
- #
# Should we build a JDK/JVM with headful support (ie a graphical ui)?
# We always build headless support.
- #
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking headful support" >&5
$as_echo_n "checking headful support... " >&6; }
# Check whether --enable-headful was given.
@@ -23159,25 +23177,7 @@
- # Control wether Hotspot runs Queens test after build.
- # Check whether --enable-hotspot-test-in-build was given.
-if test "${enable_hotspot_test_in_build+set}" = set; then :
- enableval=$enable_hotspot_test_in_build;
-else
- enable_hotspot_test_in_build=no
-fi
-
- if test "x$enable_hotspot_test_in_build" = "xyes"; then
- TEST_IN_BUILD=true
- else
- TEST_IN_BUILD=false
- fi
-
-
- ###############################################################################
- #
# Choose cacerts source file
- #
# Check whether --with-cacerts-file was given.
if test "${with_cacerts_file+set}" = set; then :
@@ -23189,10 +23189,7 @@
fi
- ###############################################################################
- #
# Enable or disable unlimited crypto
- #
# Check whether --enable-unlimited-crypto was given.
if test "${enable_unlimited_crypto+set}" = set; then :
enableval=$enable_unlimited_crypto;
@@ -23207,10 +23204,7 @@
fi
- ###############################################################################
- #
# Compress jars
- #
COMPRESS_JARS=false
@@ -23232,6 +23226,22 @@
+ # Control wether Hotspot runs Queens test after build.
+ # Check whether --enable-hotspot-test-in-build was given.
+if test "${enable_hotspot_test_in_build+set}" = set; then :
+ enableval=$enable_hotspot_test_in_build;
+else
+ enable_hotspot_test_in_build=no
+fi
+
+ if test "x$enable_hotspot_test_in_build" = "xyes"; then
+ TEST_IN_BUILD=true
+ else
+ TEST_IN_BUILD=false
+ fi
+
+
+
# Warn user that old version arguments are deprecated.
@@ -31432,7 +31442,11 @@
# The microsoft toolchain also requires INCLUDE and LIB to be set.
export INCLUDE="$VS_INCLUDE"
export LIB="$VS_LIB"
- fi
+ else
+ # Currently we do not define this for other toolchains. This might change as the need arise.
+ TOOLCHAIN_VERSION=
+ fi
+
# For solaris we really need solaris tools, and not the GNU equivalent.
# The build tools on Solaris reside in /usr/ccs (C Compilation System),
@@ -45214,6 +45228,7 @@
BUILD_AS="$BUILD_CC -c"
# Just like for the target compiler, use the compiler as linker
BUILD_LD="$BUILD_CC"
+ BUILD_LDCXX="$BUILD_CXX"
PATH="$OLDPATH"
else
@@ -45222,6 +45237,7 @@
BUILD_CC="$CC"
BUILD_CXX="$CXX"
BUILD_LD="$LD"
+ BUILD_LDCXX="$LDCXX"
BUILD_NM="$NM"
BUILD_AS="$AS"
BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
@@ -45239,6 +45255,7 @@
+
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
# For hotspot, we need these in Windows mixed path,
# so rewrite them all. Need added .exe suffix.
@@ -45398,7 +45415,7 @@
# "-z relro" supported in GNU binutils 2.17 and later
- LINKER_RELRO_FLAG="-Xlinker -z -Xlinker relro"
+ LINKER_RELRO_FLAG="-Wl,-z,relro"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if linker supports \"$LINKER_RELRO_FLAG\"" >&5
$as_echo_n "checking if linker supports \"$LINKER_RELRO_FLAG\"... " >&6; }
@@ -45448,7 +45465,7 @@
# "-z now" supported in GNU binutils 2.11 and later
- LINKER_NOW_FLAG="-Xlinker -z -Xlinker now"
+ LINKER_NOW_FLAG="-Wl,-z,now"
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if linker supports \"$LINKER_NOW_FLAG\"" >&5
$as_echo_n "checking if linker supports \"$LINKER_NOW_FLAG\"... " >&6; }
@@ -45506,7 +45523,7 @@
$as_echo_n "checking for broken SuSE 'ld' which only understands anonymous version tags in executables... " >&6; }
$ECHO "SUNWprivate_1.1 { local: *; };" > version-script.map
$ECHO "int main() { }" > main.c
- if $CXX -Xlinker -version-script=version-script.map main.c 2>&5 >&5; then
+ if $CXX -Wl,-version-script=version-script.map main.c 2>&5 >&5; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
USING_BROKEN_SUSE_LD=no
@@ -45905,12 +45922,16 @@
- # Option used to tell the compiler whether to create 32- or 64-bit executables
+ # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output
+ # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler
if test "x$TOOLCHAIN_TYPE" = xxlc; then
COMPILER_TARGET_BITS_FLAG="-q"
+ COMPILER_COMMAND_FILE_FLAG="-f"
else
COMPILER_TARGET_BITS_FLAG="-m"
- fi
+ COMPILER_COMMAND_FILE_FLAG="@"
+ fi
+
# FIXME: figure out if we should select AR flags depending on OS or toolchain.
@@ -46646,37 +46667,38 @@
else
SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
fi
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/$1'
+ SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/$1'
SET_SHARED_LIBRARY_MAPFILE=''
else
# Default works for linux, might work on other platforms as well.
SHARED_LIBRARY_FLAGS='-shared'
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN$1'
- SET_SHARED_LIBRARY_ORIGIN="-Xlinker -z -Xlinker origin $SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -soname=$1'
- SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=$1'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1'
+ SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
+ SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1'
+ SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1'
fi
elif test "x$TOOLCHAIN_TYPE" = xclang; then
- PICFLAG=''
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
# Linking is different on MacOSX
+ PICFLAG=''
SHARED_LIBRARY_FLAGS="-dynamiclib -compatibility_version 1.0.0 -current_version 1.0.0 $PICFLAG"
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker @loader_path/.'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,@loader_path/.'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -install_name -Xlinker @rpath/$1'
+ SET_SHARED_LIBRARY_NAME='-Wl,-install_name,@rpath/$1'
SET_SHARED_LIBRARY_MAPFILE=''
else
# Default works for linux, might work on other platforms as well.
+ PICFLAG='-fPIC'
SHARED_LIBRARY_FLAGS='-shared'
- SET_EXECUTABLE_ORIGIN='-Xlinker -rpath -Xlinker \$$$$ORIGIN$1'
- SET_SHARED_LIBRARY_ORIGIN="-Xlinker -z -Xlinker origin $SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME='-Xlinker -soname=$1'
- SET_SHARED_LIBRARY_MAPFILE='-Xlinker -version-script=$1'
+ SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1'
+ SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
+ SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1'
+ SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1'
fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
PICFLAG="-KPIC"
@@ -46685,7 +46707,7 @@
SHARED_LIBRARY_FLAGS="-G"
SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN$1'
SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
- SET_SHARED_LIBRARY_NAME=''
+ SET_SHARED_LIBRARY_NAME='-h $1'
SET_SHARED_LIBRARY_MAPFILE='-M$1'
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
PICFLAG="-qpic=large"
@@ -46700,7 +46722,7 @@
PICFLAG=""
C_FLAG_REORDER=''
CXX_FLAG_REORDER=''
- SHARED_LIBRARY_FLAGS="-LD"
+ SHARED_LIBRARY_FLAGS="-dll"
SET_EXECUTABLE_ORIGIN=''
SET_SHARED_LIBRARY_ORIGIN=''
SET_SHARED_LIBRARY_NAME=''
@@ -46714,6 +46736,7 @@
+
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
CFLAGS_JDK="${CFLAGS_JDK} -D__solaris__"
CXXFLAGS_JDK="${CXXFLAGS_JDK} -D__solaris__"
@@ -47022,6 +47045,25 @@
CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
;;
esac
+ elif test "x$TOOLCHAIN_TYPE" = xclang; then
+ if test "x$OPENJDK_TARGET_OS" = xlinux; then
+ if test "x$OPENJDK_TARGET_CPU" = xx86; then
+ # Force compatibility with i586 on 32 bit intel platforms.
+ COMMON_CCXXFLAGS="${COMMON_CCXXFLAGS} -march=i586"
+ fi
+ COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -Wall -Wextra -Wno-unused -Wno-unused-parameter -Wformat=2 \
+ -pipe -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE"
+ case $OPENJDK_TARGET_CPU_ARCH in
+ ppc )
+ # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing
+ CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
+ ;;
+ * )
+ COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer"
+ CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
+ ;;
+ esac
+ fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS $COMMON_CCXXFLAGS_JDK -DTRACING -DMACRO_MEMSYS_OPS -DBREAKPTS"
if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86; then
@@ -47197,17 +47239,17 @@
# If this is a --hash-style=gnu system, use --hash-style=both, why?
# We have previously set HAS_GNU_HASH if this is the case
if test -n "$HAS_GNU_HASH"; then
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker --hash-style=both"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,--hash-style=both"
fi
if test "x$OPENJDK_TARGET_OS" = xlinux; then
# And since we now know that the linker is gnu, then add -z defs, to forbid
# undefined symbols in object files.
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -z -Xlinker defs"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,-z,defs"
case $DEBUG_LEVEL in
release )
# tell linker to optimize libraries.
# Should this be supplied to the OSS linker as well?
- LDFLAGS_JDK="${LDFLAGS_JDK} -Xlinker -O1"
+ LDFLAGS_JDK="${LDFLAGS_JDK} -Wl,-O1"
;;
slowdebug )
if test "x$HAS_LINKER_NOW" = "xtrue"; then
@@ -47234,7 +47276,7 @@
esac
fi
elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
- LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext"
+ LDFLAGS_JDK="$LDFLAGS_JDK -Wl,-z,defs -xildoff -ztext"
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib"
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -bexpall -bernotok"
@@ -47252,17 +47294,19 @@
fi
LDFLAGS_JDKEXE="${LDFLAGS_JDKEXE} /STACK:$LDFLAGS_STACK_SIZE"
elif test "x$OPENJDK_TARGET_OS" = xlinux; then
- LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Xlinker --allow-shlib-undefined"
+ LDFLAGS_JDKEXE="$LDFLAGS_JDKEXE -Wl,--allow-shlib-undefined"
fi
# Customize LDFLAGS for libs
LDFLAGS_JDKLIB="${LDFLAGS_JDK}"
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}"
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
- LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -dll -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
+ -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
JDKLIB_LIBS=""
else
- LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS} \
+ LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} \
-L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
# On some platforms (mac) the linker warns about non existing -L dirs.
@@ -47657,8 +47701,21 @@
# Check whether --with-native-debug-symbols was given.
if test "${with_native_debug_symbols+set}" = set; then :
withval=$with_native_debug_symbols;
-else
- with_native_debug_symbols="zipped"
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ if test "x$withval" = xexternal || test "x$withval" = xzipped; then
+ as_fn_error $? "AIX only supports the parameters 'none' and 'internal' for --with-native-debug-symbols" "$LINENO" 5
+ fi
+ fi
+
+else
+
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ # AIX doesn't support 'zipped' so use 'internal' as default
+ with_native_debug_symbols="internal"
+ else
+ with_native_debug_symbols="zipped"
+ fi
+
fi
NATIVE_DEBUG_SYMBOLS=$with_native_debug_symbols
@@ -53467,6 +53524,1485 @@
fi
fi
+ if test "x$FOUND_FREETYPE" != xyes; then
+ FREETYPE_BASE_DIR="$HOME/freetype"
+
+ windows_path="$FREETYPE_BASE_DIR"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ FREETYPE_BASE_DIR="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ FREETYPE_BASE_DIR="$unix_path"
+ fi
+
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+ POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib64"
+ METHOD="well-known location"
+
+ # Let's start with an optimistic view of the world :-)
+ FOUND_FREETYPE=yes
+
+ # First look for the canonical freetype main include file ft2build.h.
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Fail.
+ FOUND_FREETYPE=no
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+ # Include file found, let's continue the sanity check.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+
+ # Reset to default value
+ FREETYPE_BASE_NAME=freetype
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+ if test "x$OPENJDK_TARGET_OS" = xmacosx \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
+ # On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
+ # for the .6 version explicitly.
+ FREETYPE_BASE_NAME=freetype.6
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Compensating for missing symlink by using version 6 explicitly" >&5
+$as_echo "$as_me: Compensating for missing symlink by using version 6 explicitly" >&6;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ else
+ if test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # On Windows, we will need both .lib and .dll file.
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+ # Found lib in isa dir, use that instead.
+ POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&5
+$as_echo "$as_me: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&6;}
+ fi
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+ FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+ fi
+
+ else
+
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+ POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib32"
+ METHOD="well-known location"
+
+ # Let's start with an optimistic view of the world :-)
+ FOUND_FREETYPE=yes
+
+ # First look for the canonical freetype main include file ft2build.h.
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Fail.
+ FOUND_FREETYPE=no
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+ # Include file found, let's continue the sanity check.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+
+ # Reset to default value
+ FREETYPE_BASE_NAME=freetype
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+ if test "x$OPENJDK_TARGET_OS" = xmacosx \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
+ # On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
+ # for the .6 version explicitly.
+ FREETYPE_BASE_NAME=freetype.6
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Compensating for missing symlink by using version 6 explicitly" >&5
+$as_echo "$as_me: Compensating for missing symlink by using version 6 explicitly" >&6;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ else
+ if test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # On Windows, we will need both .lib and .dll file.
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+ # Found lib in isa dir, use that instead.
+ POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&5
+$as_echo "$as_me: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&6;}
+ fi
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+ FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+ fi
+
+ fi
+ if test "x$FOUND_FREETYPE" != xyes && test -d $FREETYPE_BASE_DIR \
+ && test -s "$FREETYPE_BASE_DIR/builds/windows/vc2010/freetype.vcxproj" && test "x$MSBUILD" != x; then
+ # Source is available, as a last resort try to build freetype in default location
+
+ FREETYPE_SRC_PATH="$FREETYPE_BASE_DIR"
+ BUILD_FREETYPE=yes
+
+ # Check if the freetype sources are acessible..
+ if ! test -d $FREETYPE_SRC_PATH; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-freetype-src specified, but can not find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: --with-freetype-src specified, but can not find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&2;}
+ BUILD_FREETYPE=no
+ fi
+ # ..and contain a vc2010 project file
+ vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj"
+ if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: Can not find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&2;}
+ BUILD_FREETYPE=no
+ fi
+ # Now check if configure found a version of 'msbuild.exe'
+ if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can not find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&5
+$as_echo "$as_me: WARNING: Can not find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&2;}
+ BUILD_FREETYPE=no
+ fi
+
+ # Ready to go..
+ if test "x$BUILD_FREETYPE" = xyes; then
+ # msbuild requires trailing slashes for output directories
+ freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/"
+ freetype_lib_path_unix="$freetype_lib_path"
+ freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/"
+
+ unix_path="$vcxproj_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ windows_path=`$CYGPATH -m "$unix_path"`
+ vcxproj_path="$windows_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ windows_path=`cmd //c echo $unix_path`
+ vcxproj_path="$windows_path"
+ fi
+
+
+ unix_path="$freetype_lib_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ windows_path=`$CYGPATH -m "$unix_path"`
+ freetype_lib_path="$windows_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ windows_path=`cmd //c echo $unix_path`
+ freetype_lib_path="$windows_path"
+ fi
+
+
+ unix_path="$freetype_obj_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ windows_path=`$CYGPATH -m "$unix_path"`
+ freetype_obj_path="$windows_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ windows_path=`cmd //c echo $unix_path`
+ freetype_obj_path="$windows_path"
+ fi
+
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+ freetype_platform=x64
+ else
+ freetype_platform=win32
+ fi
+
+ # The original freetype project file is for VS 2010 (i.e. 'v100'),
+ # so we have to adapt the toolset if building with any other toolsed (i.e. SDK).
+ # Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/
+ # 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&5
+$as_echo "$as_me: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&6;}
+
+ # First we try to build the freetype.dll
+ $ECHO -e "@echo off\n"\
+ "$MSBUILD $vcxproj_path "\
+ "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+ "/p:Configuration=\"Release Multithreaded\" "\
+ "/p:Platform=$freetype_platform "\
+ "/p:ConfigurationType=DynamicLibrary "\
+ "/p:TargetName=freetype "\
+ "/p:OutDir=\"$freetype_lib_path\" "\
+ "/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat
+ cmd /c freetype.bat
+
+ if test -s "$freetype_lib_path_unix/freetype.dll"; then
+ # If that succeeds we also build freetype.lib
+ $ECHO -e "@echo off\n"\
+ "$MSBUILD $vcxproj_path "\
+ "/p:PlatformToolset=$PLATFORM_TOOLSET "\
+ "/p:Configuration=\"Release Multithreaded\" "\
+ "/p:Platform=$freetype_platform "\
+ "/p:ConfigurationType=StaticLibrary "\
+ "/p:TargetName=freetype "\
+ "/p:OutDir=\"$freetype_lib_path\" "\
+ "/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat
+ cmd /c freetype.bat
+
+ if test -s "$freetype_lib_path_unix/freetype.lib"; then
+ # Once we build both, lib and dll, set freetype lib and include path appropriately
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include"
+ POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling freetype sources succeeded! (see freetype.log for build results)" >&5
+$as_echo "$as_me: Compiling freetype sources succeeded! (see freetype.log for build results)" >&6;}
+ else
+ BUILD_FREETYPE=no
+ fi
+ else
+ BUILD_FREETYPE=no
+ fi
+ fi
+
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+ POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib64"
+ METHOD="well-known location"
+
+ # Let's start with an optimistic view of the world :-)
+ FOUND_FREETYPE=yes
+
+ # First look for the canonical freetype main include file ft2build.h.
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Fail.
+ FOUND_FREETYPE=no
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+ # Include file found, let's continue the sanity check.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+
+ # Reset to default value
+ FREETYPE_BASE_NAME=freetype
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+ if test "x$OPENJDK_TARGET_OS" = xmacosx \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
+ # On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
+ # for the .6 version explicitly.
+ FREETYPE_BASE_NAME=freetype.6
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Compensating for missing symlink by using version 6 explicitly" >&5
+$as_echo "$as_me: Compensating for missing symlink by using version 6 explicitly" >&6;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ else
+ if test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # On Windows, we will need both .lib and .dll file.
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+ # Found lib in isa dir, use that instead.
+ POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&5
+$as_echo "$as_me: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&6;}
+ fi
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+ FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+ fi
+
+ else
+
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include"
+ POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib32"
+ METHOD="well-known location"
+
+ # Let's start with an optimistic view of the world :-)
+ FOUND_FREETYPE=yes
+
+ # First look for the canonical freetype main include file ft2build.h.
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
+ if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
+ # Fail.
+ FOUND_FREETYPE=no
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+ # Include file found, let's continue the sanity check.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5
+$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;}
+
+ # Reset to default value
+ FREETYPE_BASE_NAME=freetype
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
+ if test "x$OPENJDK_TARGET_OS" = xmacosx \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
+ # On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
+ # for the .6 version explicitly.
+ FREETYPE_BASE_NAME=freetype.6
+ FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Compensating for missing symlink by using version 6 explicitly" >&5
+$as_echo "$as_me: Compensating for missing symlink by using version 6 explicitly" >&6;}
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ else
+ if test "x$OPENJDK_TARGET_OS" = xwindows; then
+ # On Windows, we will need both .lib and .dll file.
+ if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&5
+$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location." >&6;}
+ FOUND_FREETYPE=no
+ fi
+ elif test "x$OPENJDK_TARGET_OS" = xsolaris \
+ && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
+ # Found lib in isa dir, use that instead.
+ POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&5
+$as_echo "$as_me: Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead" >&6;}
+ fi
+ fi
+ fi
+
+ if test "x$FOUND_FREETYPE" = xyes; then
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ # Only process if variable expands to non-empty
+
+ if test "x$POTENTIAL_FREETYPE_LIB_PATH" != x; then
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+ # Input might be given as Windows format, start by converting to
+ # unix format.
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ new_path=`$CYGPATH -u "$path"`
+
+ # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+ # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+ # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+ # "foo.exe" is OK but "foo" is an error.
+ #
+ # This test is therefore slightly more accurate than "test -f" to check for file precense.
+ # It is also a way to make sure we got the proper file name for the real test later on.
+ test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+ if test "x$test_shortpath" = x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5
+ fi
+
+ # Call helper function which possibly converts this using DOS-style short mode.
+ # If so, the updated path is stored in $new_path.
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+ path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+ if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+ # Going to short mode and back again did indeed matter. Since short mode is
+ # case insensitive, let's make it lowercase to improve readability.
+ shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ # Now convert it back to Unix-style (cygpath)
+ input_path=`$CYGPATH -u "$shortmode_path"`
+ new_path="$input_path"
+ fi
+ fi
+
+ test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+ if test "x$test_cygdrive_prefix" = x; then
+ # As a simple fix, exclude /usr/bin since it's not a real path.
+ if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+ # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+ # a path prefixed by /cygdrive for fixpath to work.
+ new_path="$CYGWIN_ROOT_PATH$input_path"
+ fi
+ fi
+
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_colon=`$ECHO $path | $GREP ^.:`
+ new_path="$path"
+ if test "x$has_colon" = x; then
+ # Not in mixed or Windows style, start by that.
+ new_path=`cmd //c echo $path`
+ fi
+
+
+ input_path="$new_path"
+ # Check if we need to convert this using DOS-style short mode. If the path
+ # contains just simple characters, use it. Otherwise (spaces, weird characters),
+ # take no chances and rewrite it.
+ # Note: m4 eats our [], so we need to use [ and ] instead.
+ has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+ if test "x$has_forbidden_chars" != x; then
+ # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+ new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ fi
+
+
+ windows_path="$new_path"
+ if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+ unix_path=`$CYGPATH -u "$windows_path"`
+ new_path="$unix_path"
+ elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+ unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+ new_path="$unix_path"
+ fi
+
+ if test "x$path" != "x$new_path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="$new_path"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;}
+ fi
+
+ # Save the first 10 bytes of this path to the storage, so fixpath can work.
+ all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+ else
+ # We're on a unix platform. Hooray! :)
+ path="$POTENTIAL_FREETYPE_LIB_PATH"
+ has_space=`$ECHO "$path" | $GREP " "`
+ if test "x$has_space" != x; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;}
+ as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+ fi
+
+ # Use eval to expand a potential ~
+ eval path="$path"
+ if test ! -f "$path" && test ! -d "$path"; then
+ as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5
+ fi
+
+ if test -d "$path"; then
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`"
+ else
+ dir="`$DIRNAME "$path"`"
+ base="`$BASENAME "$path"`"
+ POTENTIAL_FREETYPE_LIB_PATH="`cd "$dir"; $THEPWDCMD -L`/$base"
+ fi
+ fi
+ fi
+
+
+ FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5
+$as_echo_n "checking for freetype includes... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5
+$as_echo "$FREETYPE_INCLUDE_PATH" >&6; }
+ FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5
+$as_echo_n "checking for freetype libraries... " >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5
+$as_echo "$FREETYPE_LIB_PATH" >&6; }
+ fi
+
+ fi
+ fi
+ fi
else
FREETYPE_BASE_DIR="$SYSROOT/usr"
@@ -57085,13 +58621,6 @@
HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET"
- # The name of the Service Agent jar.
- SALIB_NAME="${LIBRARY_PREFIX}saproc${SHARED_LIBRARY_SUFFIX}"
- if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
- SALIB_NAME="${LIBRARY_PREFIX}sawindbg${SHARED_LIBRARY_SUFFIX}"
- fi
-
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if elliptic curve crypto implementation is present" >&5
$as_echo_n "checking if elliptic curve crypto implementation is present... " >&6; }
@@ -57253,6 +58782,21 @@
+ # The number of test jobs will be chosen automatically if TEST_JOBS is 0
+
+# Check whether --with-test-jobs was given.
+if test "${with_test_jobs+set}" = set; then :
+ withval=$with_test_jobs;
+fi
+
+ if test "x$with_test_jobs" = x; then
+ TEST_JOBS=0
+ else
+ TEST_JOBS=$with_test_jobs
+ fi
+
+
+
# Setup arguments for the boot jdk (after cores and memory have been setup)
##############################################################################
--- a/common/autoconf/help.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/help.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -86,7 +86,11 @@
automatically build the freetype library into '<freetype_src>/lib64' for 64-bit
builds or into '<freetype_src>/lib32' for 32-bit builds.
Afterwards you can always use '--with-freetype-include=<freetype_src>/include'
-and '--with-freetype-lib=<freetype_src>/lib[32|64]' for other builds."
+and '--with-freetype-lib=<freetype_src>/lib[32|64]' for other builds.
+
+Alternatively you can unpack the sources like this to use the default directory:
+
+tar --one-top-level=$HOME/freetype --strip-components=1 -xzf freetype-2.5.3.tar.gz"
;;
esac
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/common/autoconf/hotspot.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,268 @@
+#
+# Copyright (c) 2011, 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.
+#
+
+###############################################################################
+# Check which interpreter of the JVM we want to build.
+# Currently we have:
+# template: Template interpreter (the default)
+# cpp : C++ interpreter
+AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_INTERPRETER],
+[
+ AC_ARG_WITH([jvm-interpreter], [AS_HELP_STRING([--with-jvm-interpreter],
+ [JVM interpreter to build (template, cpp) @<:@template@:>@])])
+
+ AC_MSG_CHECKING([which interpreter of the JVM to build])
+ if test "x$with_jvm_interpreter" = x; then
+ JVM_INTERPRETER="template"
+ else
+ JVM_INTERPRETER="$with_jvm_interpreter"
+ fi
+ AC_MSG_RESULT([$JVM_INTERPRETER])
+
+ if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then
+ AC_MSG_ERROR([The available JVM interpreters are: template, cpp])
+ fi
+
+ AC_SUBST(JVM_INTERPRETER)
+])
+
+###############################################################################
+# Check which variants of the JVM that we want to build.
+# Currently we have:
+# server: normal interpreter and a C2 or tiered C1/C2 compiler
+# client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms)
+# minimal1: reduced form of client with optional VM services and features stripped out
+# zero: no machine code interpreter, no compiler
+# zeroshark: zero interpreter and shark/llvm compiler backend
+# core: interpreter only, no compiler (only works on some platforms)
+AC_DEFUN_ONCE([HOTSPOT_SETUP_JVM_VARIANTS],
+[
+ AC_MSG_CHECKING([which variants of the JVM to build])
+ AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants],
+ [JVM variants (separated by commas) to build (server, client, minimal1, zero, zeroshark, core) @<:@server@:>@])])
+
+ if test "x$with_jvm_variants" = x; then
+ with_jvm_variants="server"
+ fi
+
+ JVM_VARIANTS=",$with_jvm_variants,"
+ TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'`
+
+ if test "x$TEST_VARIANTS" != "x,"; then
+ AC_MSG_ERROR([The available JVM variants are: server, client, minimal1, zero, zeroshark, core])
+ fi
+ AC_MSG_RESULT([$with_jvm_variants])
+
+ JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'`
+ JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'`
+ JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'`
+ JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'`
+ JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'`
+ JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'`
+
+ if test "x$JVM_VARIANT_CLIENT" = xtrue; then
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+ AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.])
+ fi
+ fi
+ if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+ AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.])
+ fi
+ fi
+
+ # Replace the commas with AND for use in the build directory name.
+ ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'`
+ COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
+ if test "x$COUNT_VARIANTS" != "x,1"; then
+ BUILDING_MULTIPLE_JVM_VARIANTS=yes
+ else
+ BUILDING_MULTIPLE_JVM_VARIANTS=no
+ fi
+
+ if test "x$JVM_VARIANT_ZERO" = xtrue && test "x$BUILDING_MULTIPLE_JVM_VARIANTS" = xyes; then
+ AC_MSG_ERROR([You cannot build multiple variants with zero.])
+ fi
+
+ AC_SUBST(JVM_VARIANTS)
+ AC_SUBST(JVM_VARIANT_SERVER)
+ AC_SUBST(JVM_VARIANT_CLIENT)
+ AC_SUBST(JVM_VARIANT_MINIMAL1)
+ AC_SUBST(JVM_VARIANT_ZERO)
+ AC_SUBST(JVM_VARIANT_ZEROSHARK)
+ AC_SUBST(JVM_VARIANT_CORE)
+
+ INCLUDE_SA=true
+ if test "x$JVM_VARIANT_ZERO" = xtrue ; then
+ INCLUDE_SA=false
+ fi
+ if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then
+ INCLUDE_SA=false
+ fi
+ if test "x$OPENJDK_TARGET_OS" = xaix ; then
+ INCLUDE_SA=false
+ fi
+ if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
+ INCLUDE_SA=false
+ fi
+ AC_SUBST(INCLUDE_SA)
+
+ if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
+ MACOSX_UNIVERSAL="true"
+ fi
+
+ AC_SUBST(MACOSX_UNIVERSAL)
+])
+
+
+###############################################################################
+# Setup legacy vars/targets and new vars to deal with different debug levels.
+#
+# release: no debug information, all optimizations, no asserts.
+# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
+# fastdebug: debug information (-g), all optimizations, all asserts
+# slowdebug: debug information (-g), no optimizations, all asserts
+#
+AC_DEFUN_ONCE([HOTSPOT_SETUP_DEBUG_LEVEL],
+[
+ case $DEBUG_LEVEL in
+ release )
+ VARIANT="OPT"
+ FASTDEBUG="false"
+ DEBUG_CLASSFILES="false"
+ BUILD_VARIANT_RELEASE=""
+ HOTSPOT_DEBUG_LEVEL="product"
+ HOTSPOT_EXPORT="product"
+ ;;
+ fastdebug )
+ VARIANT="DBG"
+ FASTDEBUG="true"
+ DEBUG_CLASSFILES="true"
+ BUILD_VARIANT_RELEASE="-fastdebug"
+ HOTSPOT_DEBUG_LEVEL="fastdebug"
+ HOTSPOT_EXPORT="fastdebug"
+ ;;
+ slowdebug )
+ VARIANT="DBG"
+ FASTDEBUG="false"
+ DEBUG_CLASSFILES="true"
+ BUILD_VARIANT_RELEASE="-debug"
+ HOTSPOT_DEBUG_LEVEL="debug"
+ HOTSPOT_EXPORT="debug"
+ ;;
+ optimized )
+ VARIANT="OPT"
+ FASTDEBUG="false"
+ DEBUG_CLASSFILES="false"
+ BUILD_VARIANT_RELEASE="-optimized"
+ HOTSPOT_DEBUG_LEVEL="optimized"
+ HOTSPOT_EXPORT="optimized"
+ ;;
+ esac
+
+ # The debug level 'optimized' is a little special because it is currently only
+ # applicable to the HotSpot build where it means to build a completely
+ # optimized version of the VM without any debugging code (like for the
+ # 'release' debug level which is called 'product' in the HotSpot build) but
+ # with the exception that it can contain additional code which is otherwise
+ # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to
+ # test new and/or experimental features which are not intended for customer
+ # shipment. Because these new features need to be tested and benchmarked in
+ # real world scenarios, we want to build the containing JDK at the 'release'
+ # debug level.
+ if test "x$DEBUG_LEVEL" = xoptimized; then
+ DEBUG_LEVEL="release"
+ fi
+
+ #####
+ # Generate the legacy makefile targets for hotspot.
+ # The hotspot api for selecting the build artifacts, really, needs to be improved.
+ # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to
+ # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc
+ # But until then ...
+ HOTSPOT_TARGET=""
+
+ if test "x$JVM_VARIANT_SERVER" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} "
+ fi
+
+ if test "x$JVM_VARIANT_CLIENT" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 "
+ fi
+
+ if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 "
+ fi
+
+ if test "x$JVM_VARIANT_ZERO" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero "
+ fi
+
+ if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark "
+ fi
+
+ if test "x$JVM_VARIANT_CORE" = xtrue; then
+ HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core "
+ fi
+
+ HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT"
+
+ # On Macosx universal binaries are produced, but they only contain
+ # 64 bit intel. This invalidates control of which jvms are built
+ # from configure, but only server is valid anyway. Fix this
+ # when hotspot makefiles are rewritten.
+ if test "x$MACOSX_UNIVERSAL" = xtrue; then
+ HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT}
+ fi
+
+ #####
+
+ AC_SUBST(DEBUG_LEVEL)
+ AC_SUBST(VARIANT)
+ AC_SUBST(FASTDEBUG)
+ AC_SUBST(DEBUG_CLASSFILES)
+ AC_SUBST(BUILD_VARIANT_RELEASE)
+])
+
+AC_DEFUN_ONCE([HOTSPOT_SETUP_HOTSPOT_OPTIONS],
+[
+ # Control wether Hotspot runs Queens test after build.
+ AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build],
+ [run the Queens test after Hotspot build @<:@disabled@:>@])],,
+ [enable_hotspot_test_in_build=no])
+ if test "x$enable_hotspot_test_in_build" = "xyes"; then
+ TEST_IN_BUILD=true
+ else
+ TEST_IN_BUILD=false
+ fi
+ AC_SUBST(TEST_IN_BUILD)
+])
+
+AC_DEFUN_ONCE([HOTSPOT_SETUP_BUILD_TWEAKS],
+[
+ HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET"
+ AC_SUBST(HOTSPOT_MAKE_ARGS)
+])
--- a/common/autoconf/jdk-options.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/jdk-options.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -23,19 +23,16 @@
# questions.
#
+###############################################################################
+# Check which variant of the JDK that we want to build.
+# Currently we have:
+# normal: standard edition
+# but the custom make system may add other variants
+#
+# Effectively the JDK variant gives a name to a specific set of
+# modules to compile into the JDK.
AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_VARIANT],
[
- ###############################################################################
- #
- # Check which variant of the JDK that we want to build.
- # Currently we have:
- # normal: standard edition
- # but the custom make system may add other variants
- #
- # Effectively the JDK variant gives a name to a specific set of
- # modules to compile into the JDK. In the future, these modules
- # might even be Jigsaw modules.
- #
AC_MSG_CHECKING([which variant of the JDK to build])
AC_ARG_WITH([jdk-variant], [AS_HELP_STRING([--with-jdk-variant],
[JDK variant to build (normal) @<:@normal@:>@])])
@@ -51,138 +48,14 @@
AC_MSG_RESULT([$JDK_VARIANT])
])
-AC_DEFUN_ONCE([JDKOPT_SETUP_JVM_INTERPRETER],
-[
###############################################################################
-#
-# Check which interpreter of the JVM we want to build.
-# Currently we have:
-# template: Template interpreter (the default)
-# cpp : C++ interpreter
-AC_MSG_CHECKING([which interpreter of the JVM to build])
-AC_ARG_WITH([jvm-interpreter], [AS_HELP_STRING([--with-jvm-interpreter],
- [JVM interpreter to build (template, cpp) @<:@template@:>@])])
-
-if test "x$with_jvm_interpreter" = x; then
- with_jvm_interpreter="template"
-fi
-
-JVM_INTERPRETER="$with_jvm_interpreter"
-
-if test "x$JVM_INTERPRETER" != xtemplate && test "x$JVM_INTERPRETER" != xcpp; then
- AC_MSG_ERROR([The available JVM interpreters are: template, cpp])
-fi
-
-AC_SUBST(JVM_INTERPRETER)
-
-AC_MSG_RESULT([$with_jvm_interpreter])
-])
-
-AC_DEFUN_ONCE([JDKOPT_SETUP_JVM_VARIANTS],
-[
-
- ###############################################################################
- #
- # Check which variants of the JVM that we want to build.
- # Currently we have:
- # server: normal interpreter and a tiered C1/C2 compiler
- # client: normal interpreter and C1 (no C2 compiler) (only 32-bit platforms)
- # minimal1: reduced form of client with optional VM services and features stripped out
- # kernel: kernel footprint JVM that passes the TCK without major performance problems,
- # ie normal interpreter and C1, only the serial GC, kernel jvmti etc
- # zero: no machine code interpreter, no compiler
- # zeroshark: zero interpreter and shark/llvm compiler backend
-# core: interpreter only, no compiler (only works on some platforms)
- AC_MSG_CHECKING([which variants of the JVM to build])
- AC_ARG_WITH([jvm-variants], [AS_HELP_STRING([--with-jvm-variants],
- [JVM variants (separated by commas) to build (server, client, minimal1, kernel, zero, zeroshark, core) @<:@server@:>@])])
-
- if test "x$with_jvm_variants" = x; then
- with_jvm_variants="server"
- fi
-
- JVM_VARIANTS=",$with_jvm_variants,"
- TEST_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,//' -e 's/client,//' -e 's/minimal1,//' -e 's/kernel,//' -e 's/zero,//' -e 's/zeroshark,//' -e 's/core,//'`
-
- if test "x$TEST_VARIANTS" != "x,"; then
- AC_MSG_ERROR([The available JVM variants are: server, client, minimal1, kernel, zero, zeroshark, core])
- fi
- AC_MSG_RESULT([$with_jvm_variants])
-
- JVM_VARIANT_SERVER=`$ECHO "$JVM_VARIANTS" | $SED -e '/,server,/!s/.*/false/g' -e '/,server,/s/.*/true/g'`
- JVM_VARIANT_CLIENT=`$ECHO "$JVM_VARIANTS" | $SED -e '/,client,/!s/.*/false/g' -e '/,client,/s/.*/true/g'`
- JVM_VARIANT_MINIMAL1=`$ECHO "$JVM_VARIANTS" | $SED -e '/,minimal1,/!s/.*/false/g' -e '/,minimal1,/s/.*/true/g'`
- JVM_VARIANT_KERNEL=`$ECHO "$JVM_VARIANTS" | $SED -e '/,kernel,/!s/.*/false/g' -e '/,kernel,/s/.*/true/g'`
- JVM_VARIANT_ZERO=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zero,/!s/.*/false/g' -e '/,zero,/s/.*/true/g'`
- JVM_VARIANT_ZEROSHARK=`$ECHO "$JVM_VARIANTS" | $SED -e '/,zeroshark,/!s/.*/false/g' -e '/,zeroshark,/s/.*/true/g'`
- JVM_VARIANT_CORE=`$ECHO "$JVM_VARIANTS" | $SED -e '/,core,/!s/.*/false/g' -e '/,core,/s/.*/true/g'`
-
- if test "x$JVM_VARIANT_CLIENT" = xtrue; then
- if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- AC_MSG_ERROR([You cannot build a client JVM for a 64-bit machine.])
- fi
- fi
- if test "x$JVM_VARIANT_KERNEL" = xtrue; then
- if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- AC_MSG_ERROR([You cannot build a kernel JVM for a 64-bit machine.])
- fi
- fi
- if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
- if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
- AC_MSG_ERROR([You cannot build a minimal JVM for a 64-bit machine.])
- fi
- fi
-
- # Replace the commas with AND for use in the build directory name.
- ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'`
- COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/kernel,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
- if test "x$COUNT_VARIANTS" != "x,1"; then
- BUILDING_MULTIPLE_JVM_VARIANTS=yes
- else
- BUILDING_MULTIPLE_JVM_VARIANTS=no
- fi
-
- AC_SUBST(JVM_VARIANTS)
- AC_SUBST(JVM_VARIANT_SERVER)
- AC_SUBST(JVM_VARIANT_CLIENT)
- AC_SUBST(JVM_VARIANT_MINIMAL1)
- AC_SUBST(JVM_VARIANT_KERNEL)
- AC_SUBST(JVM_VARIANT_ZERO)
- AC_SUBST(JVM_VARIANT_ZEROSHARK)
- AC_SUBST(JVM_VARIANT_CORE)
-
- INCLUDE_SA=true
- if test "x$JVM_VARIANT_ZERO" = xtrue ; then
- INCLUDE_SA=false
- fi
- if test "x$JVM_VARIANT_ZEROSHARK" = xtrue ; then
- INCLUDE_SA=false
- fi
- if test "x$OPENJDK_TARGET_OS" = xaix ; then
- INCLUDE_SA=false
- fi
- if test "x$OPENJDK_TARGET_CPU" = xaarch64; then
- INCLUDE_SA=false
- fi
- AC_SUBST(INCLUDE_SA)
-
- if test "x$OPENJDK_TARGET_OS" = "xmacosx"; then
- MACOSX_UNIVERSAL="true"
- fi
-
- AC_SUBST(MACOSX_UNIVERSAL)
-])
-
+# Set the debug level
+# release: no debug information, all optimizations, no asserts.
+# optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
+# fastdebug: debug information (-g), all optimizations, all asserts
+# slowdebug: debug information (-g), no optimizations, all asserts
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_LEVEL],
[
- ###############################################################################
- #
- # Set the debug level
- # release: no debug information, all optimizations, no asserts.
- # optimized: no debug information, all optimizations, no asserts, HotSpot target is 'optimized'.
- # fastdebug: debug information (-g), all optimizations, all asserts
- # slowdebug: debug information (-g), no optimizations, all asserts
- #
DEBUG_LEVEL="release"
AC_MSG_CHECKING([which debug level to use])
AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug],
@@ -208,118 +81,8 @@
test "x$DEBUG_LEVEL" != xslowdebug; then
AC_MSG_ERROR([Allowed debug levels are: release, fastdebug and slowdebug])
fi
-
-
- ###############################################################################
- #
- # Setup legacy vars/targets and new vars to deal with different debug levels.
- #
-
- case $DEBUG_LEVEL in
- release )
- VARIANT="OPT"
- FASTDEBUG="false"
- DEBUG_CLASSFILES="false"
- BUILD_VARIANT_RELEASE=""
- HOTSPOT_DEBUG_LEVEL="product"
- HOTSPOT_EXPORT="product"
- ;;
- fastdebug )
- VARIANT="DBG"
- FASTDEBUG="true"
- DEBUG_CLASSFILES="true"
- BUILD_VARIANT_RELEASE="-fastdebug"
- HOTSPOT_DEBUG_LEVEL="fastdebug"
- HOTSPOT_EXPORT="fastdebug"
- ;;
- slowdebug )
- VARIANT="DBG"
- FASTDEBUG="false"
- DEBUG_CLASSFILES="true"
- BUILD_VARIANT_RELEASE="-debug"
- HOTSPOT_DEBUG_LEVEL="debug"
- HOTSPOT_EXPORT="debug"
- ;;
- optimized )
- VARIANT="OPT"
- FASTDEBUG="false"
- DEBUG_CLASSFILES="false"
- BUILD_VARIANT_RELEASE="-optimized"
- HOTSPOT_DEBUG_LEVEL="optimized"
- HOTSPOT_EXPORT="optimized"
- ;;
- esac
-
- # The debug level 'optimized' is a little special because it is currently only
- # applicable to the HotSpot build where it means to build a completely
- # optimized version of the VM without any debugging code (like for the
- # 'release' debug level which is called 'product' in the HotSpot build) but
- # with the exception that it can contain additional code which is otherwise
- # protected by '#ifndef PRODUCT' macros. These 'optimized' builds are used to
- # test new and/or experimental features which are not intended for customer
- # shipment. Because these new features need to be tested and benchmarked in
- # real world scenarios, we want to build the containing JDK at the 'release'
- # debug level.
- if test "x$DEBUG_LEVEL" = xoptimized; then
- DEBUG_LEVEL="release"
- fi
-
- #####
- # Generate the legacy makefile targets for hotspot.
- # The hotspot api for selecting the build artifacts, really, needs to be improved.
- # JDK-7195896 will fix this on the hotspot side by using the JVM_VARIANT_* variables to
- # determine what needs to be built. All we will need to set here is all_product, all_fastdebug etc
- # But until then ...
- HOTSPOT_TARGET=""
-
- if test "x$JVM_VARIANT_SERVER" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL} "
- fi
-
- if test "x$JVM_VARIANT_CLIENT" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}1 "
- fi
-
- if test "x$JVM_VARIANT_MINIMAL1" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}minimal1 "
- fi
-
- if test "x$JVM_VARIANT_KERNEL" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}kernel "
- fi
-
- if test "x$JVM_VARIANT_ZERO" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}zero "
- fi
-
- if test "x$JVM_VARIANT_ZEROSHARK" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}shark "
- fi
-
- if test "x$JVM_VARIANT_CORE" = xtrue; then
- HOTSPOT_TARGET="$HOTSPOT_TARGET${HOTSPOT_DEBUG_LEVEL}core "
- fi
-
- HOTSPOT_TARGET="$HOTSPOT_TARGET docs export_$HOTSPOT_EXPORT"
-
- # On Macosx universal binaries are produced, but they only contain
- # 64 bit intel. This invalidates control of which jvms are built
- # from configure, but only server is valid anyway. Fix this
- # when hotspot makefiles are rewritten.
- if test "x$MACOSX_UNIVERSAL" = xtrue; then
- HOTSPOT_TARGET=universal_${HOTSPOT_EXPORT}
- fi
-
- #####
-
- AC_SUBST(DEBUG_LEVEL)
- AC_SUBST(VARIANT)
- AC_SUBST(FASTDEBUG)
- AC_SUBST(DEBUG_CLASSFILES)
- AC_SUBST(BUILD_VARIANT_RELEASE)
])
-
###############################################################################
#
# Should we build only OpenJDK even if closed sources are present?
@@ -367,12 +130,8 @@
AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS],
[
-
- ###############################################################################
- #
# Should we build a JDK/JVM with headful support (ie a graphical ui)?
# We always build headless support.
- #
AC_MSG_CHECKING([headful support])
AC_ARG_ENABLE([headful], [AS_HELP_STRING([--disable-headful],
[disable building headful support (graphical UI support) @<:@enabled@:>@])],
@@ -398,21 +157,7 @@
AC_SUBST(SUPPORT_HEADFUL)
AC_SUBST(BUILD_HEADLESS)
- # Control wether Hotspot runs Queens test after build.
- AC_ARG_ENABLE([hotspot-test-in-build], [AS_HELP_STRING([--enable-hotspot-test-in-build],
- [run the Queens test after Hotspot build @<:@disabled@:>@])],,
- [enable_hotspot_test_in_build=no])
- if test "x$enable_hotspot_test_in_build" = "xyes"; then
- TEST_IN_BUILD=true
- else
- TEST_IN_BUILD=false
- fi
- AC_SUBST(TEST_IN_BUILD)
-
- ###############################################################################
- #
# Choose cacerts source file
- #
AC_ARG_WITH(cacerts-file, [AS_HELP_STRING([--with-cacerts-file],
[specify alternative cacerts file])])
if test "x$with_cacerts_file" != x; then
@@ -420,10 +165,7 @@
fi
AC_SUBST(CACERTS_FILE)
- ###############################################################################
- #
# Enable or disable unlimited crypto
- #
AC_ARG_ENABLE(unlimited-crypto, [AS_HELP_STRING([--enable-unlimited-crypto],
[Enable unlimited crypto policy @<:@disabled@:>@])],,
[enable_unlimited_crypto=no])
@@ -434,10 +176,7 @@
fi
AC_SUBST(UNLIMITED_CRYPTO)
- ###############################################################################
- #
# Compress jars
- #
COMPRESS_JARS=false
AC_SUBST(COMPRESS_JARS)
@@ -455,19 +194,6 @@
AC_SUBST(COPYRIGHT_YEAR)
])
-AC_DEFUN_ONCE([JDKOPT_SETUP_BUILD_TWEAKS],
-[
- HOTSPOT_MAKE_ARGS="$HOTSPOT_TARGET"
- AC_SUBST(HOTSPOT_MAKE_ARGS)
-
- # The name of the Service Agent jar.
- SALIB_NAME="${LIBRARY_PREFIX}saproc${SHARED_LIBRARY_SUFFIX}"
- if test "x$OPENJDK_TARGET_OS" = "xwindows"; then
- SALIB_NAME="${LIBRARY_PREFIX}sawindbg${SHARED_LIBRARY_SUFFIX}"
- fi
- AC_SUBST(SALIB_NAME)
-])
-
###############################################################################
#
# Enable or disable the elliptic curve crypto implementation
@@ -487,7 +213,6 @@
AC_SUBST(ENABLE_INTREE_EC)
])
-
AC_DEFUN_ONCE([JDKOPT_SETUP_DEBUG_SYMBOLS],
[
#
@@ -498,8 +223,21 @@
AC_ARG_WITH([native-debug-symbols],
[AS_HELP_STRING([--with-native-debug-symbols],
[set the native debug symbol configuration (none, internal, external, zipped) @<:@zipped@:>@])],
- [],
- [with_native_debug_symbols="zipped"])
+ [
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ if test "x$withval" = xexternal || test "x$withval" = xzipped; then
+ AC_MSG_ERROR([AIX only supports the parameters 'none' and 'internal' for --with-native-debug-symbols])
+ fi
+ fi
+ ],
+ [
+ if test "x$OPENJDK_TARGET_OS" = xaix; then
+ # AIX doesn't support 'zipped' so use 'internal' as default
+ with_native_debug_symbols="internal"
+ else
+ with_native_debug_symbols="zipped"
+ fi
+ ])
NATIVE_DEBUG_SYMBOLS=$with_native_debug_symbols
AC_MSG_RESULT([$NATIVE_DEBUG_SYMBOLS])
@@ -632,5 +370,3 @@
AC_SUBST(STATIC_BUILD)
])
-
-
--- a/common/autoconf/lib-freetype.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/lib-freetype.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -321,6 +321,25 @@
BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(FREETYPE_BASE_DIR)
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
+ if test "x$FOUND_FREETYPE" != xyes; then
+ FREETYPE_BASE_DIR="$HOME/freetype"
+ BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(FREETYPE_BASE_DIR)
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+ LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib64], [well-known location])
+ else
+ LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib32], [well-known location])
+ fi
+ if test "x$FOUND_FREETYPE" != xyes && test -d $FREETYPE_BASE_DIR \
+ && test -s "$FREETYPE_BASE_DIR/builds/windows/vc2010/freetype.vcxproj" && test "x$MSBUILD" != x; then
+ # Source is available, as a last resort try to build freetype in default location
+ LIB_BUILD_FREETYPE($FREETYPE_BASE_DIR)
+ if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
+ LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib64], [well-known location])
+ else
+ LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib32], [well-known location])
+ fi
+ fi
+ fi
else
FREETYPE_BASE_DIR="$SYSROOT/usr"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
--- a/common/autoconf/spec.gmk.in Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/spec.gmk.in Wed Jan 06 14:54:24 2016 +0000
@@ -204,13 +204,12 @@
# These are the libjvms that we want to build.
# The java launcher uses the default.
-# The others can be selected by specifying -client -server -minimal1 -kernel -zero or -zeroshark
+# The others can be selected by specifying -client -server -minimal1 -zero or -zeroshark
# on the java launcher command line.
JVM_VARIANTS:=@JVM_VARIANTS@
JVM_VARIANT_SERVER:=@JVM_VARIANT_SERVER@
JVM_VARIANT_CLIENT:=@JVM_VARIANT_CLIENT@
JVM_VARIANT_MINIMAL1:=@JVM_VARIANT_MINIMAL1@
-JVM_VARIANT_KERNEL:=@JVM_VARIANT_KERNEL@
JVM_VARIANT_ZERO:=@JVM_VARIANT_ZERO@
JVM_VARIANT_ZEROSHARK:=@JVM_VARIANT_ZEROSHARK@
JVM_VARIANT_CORE:=@JVM_VARIANT_CORE@
@@ -270,6 +269,7 @@
# Number of parallel jobs to use for compilation
JOBS?=@JOBS@
+TEST_JOBS?=@TEST_JOBS@
# Default make target
DEFAULT_MAKE_TARGET:=@DEFAULT_MAKE_TARGET@
@@ -280,6 +280,8 @@
CUPS_CFLAGS:=@CUPS_CFLAGS@
ALSA_LIBS:=@ALSA_LIBS@
ALSA_CFLAGS:=@ALSA_CFLAGS@
+LIBFFI_LIBS:=@LIBFFI_LIBS@
+LIBFFI_CFLAGS:=@LIBFFI_CFLAGS@
PACKAGE_PATH=@PACKAGE_PATH@
@@ -300,11 +302,15 @@
# Toolchain type: gcc, clang, solstudio, lxc, microsoft...
TOOLCHAIN_TYPE:=@TOOLCHAIN_TYPE@
+TOOLCHAIN_VERSION := @TOOLCHAIN_VERSION@
# Option used to tell the compiler whether to create 32- or 64-bit executables
COMPILER_TARGET_BITS_FLAG:=@COMPILER_TARGET_BITS_FLAG@
COMPILER_SUPPORTS_TARGET_BITS_FLAG=@COMPILER_SUPPORTS_TARGET_BITS_FLAG@
+# Option used to pass a command file to the compiler
+COMPILER_COMMAND_FILE_FLAG:=@COMPILER_COMMAND_FILE_FLAG@
+
CC_OUT_OPTION:=@CC_OUT_OPTION@
EXE_OUT_OPTION:=@EXE_OUT_OPTION@
LD_OUT_OPTION:=@LD_OUT_OPTION@
@@ -388,6 +394,7 @@
BUILD_CC:=@FIXPATH@ @BUILD_ICECC@ @BUILD_CC@
BUILD_CXX:=@FIXPATH@ @BUILD_ICECC@ @BUILD_CXX@
BUILD_LD:=@FIXPATH@ @BUILD_LD@
+BUILD_LDCXX:=@FIXPATH@ @BUILD_LDCXX@
BUILD_AS:=@FIXPATH@ @BUILD_AS@
BUILD_AR:=@FIXPATH@ @BUILD_AR@
BUILD_NM:=@FIXPATH@ @BUILD_NM@
@@ -433,6 +440,8 @@
# (Note absence of := assignment, because we do not want to evaluate the macro body here)
SET_SHARED_LIBRARY_NAME=@SET_SHARED_LIBRARY_NAME@
+SHARED_LIBRARY_FLAGS=@SHARED_LIBRARY_FLAGS@
+
# Set origin using the linker, ie use the relative path to the dependent library to find the dependees.
# (Note absence of := assignment, because we do not want to evaluate the macro body here)
SET_SHARED_LIBRARY_ORIGIN=@SET_SHARED_LIBRARY_ORIGIN@
@@ -650,9 +659,6 @@
# Misc
#
-# Name of Service Agent library
-SALIB_NAME=@SALIB_NAME@
-
INCLUDE_SA=@INCLUDE_SA@
OS_VERSION_MAJOR:=@OS_VERSION_MAJOR@
--- a/common/autoconf/toolchain.m4 Wed Jan 06 09:39:55 2016 -0500
+++ b/common/autoconf/toolchain.m4 Wed Jan 06 14:54:24 2016 +0000
@@ -216,7 +216,11 @@
# The microsoft toolchain also requires INCLUDE and LIB to be set.
export INCLUDE="$VS_INCLUDE"
export LIB="$VS_LIB"
+ else
+ # Currently we do not define this for other toolchains. This might change as the need arise.
+ TOOLCHAIN_VERSION=
fi
+ AC_SUBST(TOOLCHAIN_VERSION)
# For solaris we really need solaris tools, and not the GNU equivalent.
# The build tools on Solaris reside in /usr/ccs (C Compilation System),
@@ -731,6 +735,7 @@
BUILD_AS="$BUILD_CC -c"
# Just like for the target compiler, use the compiler as linker
BUILD_LD="$BUILD_CC"
+ BUILD_LDCXX="$BUILD_CXX"
PATH="$OLDPATH"
else
@@ -739,6 +744,7 @@
BUILD_CC="$CC"
BUILD_CXX="$CXX"
BUILD_LD="$LD"
+ BUILD_LDCXX="$LDCXX"
BUILD_NM="$NM"
BUILD_AS="$AS"
BUILD_SYSROOT_CFLAGS="$SYSROOT_CFLAGS"
@@ -749,6 +755,7 @@
AC_SUBST(BUILD_CC)
AC_SUBST(BUILD_CXX)
AC_SUBST(BUILD_LD)
+ AC_SUBST(BUILD_LDCXX)
AC_SUBST(BUILD_NM)
AC_SUBST(BUILD_AS)
AC_SUBST(BUILD_SYSROOT_CFLAGS)
@@ -822,13 +829,13 @@
[HAS_CFLAG_OPTIMIZE_DEBUG=false])
# "-z relro" supported in GNU binutils 2.17 and later
- LINKER_RELRO_FLAG="-Xlinker -z -Xlinker relro"
+ LINKER_RELRO_FLAG="-Wl,-z,relro"
FLAGS_LINKER_CHECK_ARGUMENTS([$LINKER_RELRO_FLAG],
[HAS_LINKER_RELRO=true],
[HAS_LINKER_RELRO=false])
# "-z now" supported in GNU binutils 2.11 and later
- LINKER_NOW_FLAG="-Xlinker -z -Xlinker now"
+ LINKER_NOW_FLAG="-Wl,-z,now"
FLAGS_LINKER_CHECK_ARGUMENTS([$LINKER_NOW_FLAG],
[HAS_LINKER_NOW=true],
[HAS_LINKER_NOW=false])
@@ -841,7 +848,7 @@
AC_MSG_CHECKING([for broken SuSE 'ld' which only understands anonymous version tags in executables])
$ECHO "SUNWprivate_1.1 { local: *; };" > version-script.map
$ECHO "int main() { }" > main.c
- if $CXX -Xlinker -version-script=version-script.map main.c 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD; then
+ if $CXX -Wl,-version-script=version-script.map main.c 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD; then
AC_MSG_RESULT(no)
USING_BROKEN_SUSE_LD=no
else
--- a/common/bin/compare.sh Wed Jan 06 09:39:55 2016 -0500
+++ b/common/bin/compare.sh Wed Jan 06 14:54:24 2016 +0000
@@ -37,13 +37,18 @@
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
FULLDUMP_CMD="$OTOOL -v -V -h -X -d"
LDD_CMD="$OTOOL -L"
- DIS_CMD="$OTOOL -v -t"
+ DIS_CMD="$OTOOL -v -V -t"
STAT_PRINT_SIZE="-f %z"
elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then
FULLDUMP_CMD="$DUMPBIN -all"
LDD_CMD="$DUMPBIN -dependants | $GREP .dll"
DIS_CMD="$DUMPBIN -disasm:nobytes"
STAT_PRINT_SIZE="-c %s"
+elif [ "$OPENJDK_TARGET_OS" = "aix" ]; then
+ FULLDUMP_CMD="dump -h -r -t -n -X64"
+ LDD_CMD="$LDD"
+ DIS_CMD="$OBJDUMP -d"
+ STAT_PRINT_SIZE="-c %s"
else
FULLDUMP_CMD="$READELF -a"
LDD_CMD="$LDD"
@@ -730,6 +735,9 @@
# Some symbols get seemingly random 15 character prefixes. Filter them out.
$NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SED 's/^\([a-zA-Z] [\.\$]\)[a-zA-Z0-9_\$]\{15,15\}\./\1./g' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
+ elif [ "$OPENJDK_TARGET_OS" = "aix" ]; then
+ $OBJDUMP -T $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
+ $OBJDUMP -T $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
else
$NM -a $ORIG_OTHER_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.other
$NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this
@@ -796,14 +804,21 @@
DEP_MSG=" - "
fi
+ # Some linux compilers add a unique Build ID
+ if [ "$OPENJDK_TARGET_OS" = "linux" ]; then
+ BUILD_ID_FILTER="$SED -r 's/(Build ID:) [0-9a-f]{40}/\1/'"
+ else
+ BUILD_ID_FILTER="$CAT"
+ fi
+
# Compare fulldump output
if [ -n "$FULLDUMP_CMD" ] && [ -z "$SKIP_FULLDUMP_DIFF" ]; then
if [ -z "$FULLDUMP_DIFF_FILTER" ]; then
FULLDUMP_DIFF_FILTER="$CAT"
fi
- $FULLDUMP_CMD $OTHER_FILE | eval "$FULLDUMP_DIFF_FILTER" \
+ $FULLDUMP_CMD $OTHER_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \
> $WORK_FILE_BASE.fulldump.other 2>&1
- $FULLDUMP_CMD $THIS_FILE | eval "$FULLDUMP_DIFF_FILTER" \
+ $FULLDUMP_CMD $THIS_FILE | eval "$BUILD_ID_FILTER" | eval "$FULLDUMP_DIFF_FILTER" \
> $WORK_FILE_BASE.fulldump.this 2>&1
LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this \
--- a/common/bin/compare_exceptions.sh.incl Wed Jan 06 09:39:55 2016 -0500
+++ b/common/bin/compare_exceptions.sh.incl Wed Jan 06 14:54:24 2016 +0000
@@ -57,14 +57,18 @@
./demo/jvmti/mtrace/lib/libmtrace.so
./demo/jvmti/versionCheck/lib/libversionCheck.so
./demo/jvmti/waiters/lib/libwaiters.so
+./lib/i386/client/libjsig.so
./lib/i386/client/libjvm.so
./lib/i386/libattach.so
./lib/i386/libdt_socket.so
./lib/i386/libinstrument.so
./lib/i386/libjsdt.so
+./lib/i386/libjsig.so
./lib/i386/libmanagement.so
+./lib/i386/libnet.so
./lib/i386/libnpt.so
./lib/i386/libverify.so
+./lib/i386/server/libjsig.so
./lib/i386/server/libjvm.so
./bin/appletviewer
./bin/idlj
@@ -105,6 +109,17 @@
./bin/xjc
"
+# Issue with __FILE__ usage in generated header files prevent clean fulldump diff of
+# server jvm with old hotspot build.
+KNOWN_FULLDUMP_DIFF="
+./lib/i386/server/libjvm.so
+"
+KNOWN_DIS_DIFF="
+./lib/i386/server/libjvm.so
+"
+DIS_DIFF_FILTER="$SED \
+ -e 's/\(:\t\)\([0-9a-z]\{2,2\} \)\{1,7\}/\1<hex>/g' \
+ -e 's/0x[0-9a-z]\{2,9\}/<hex>/g'"
fi
if [ "$OPENJDK_TARGET_OS" = "linux" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
@@ -135,6 +150,7 @@
./lib/amd64/libjsdt.so
./lib/amd64/libjsig.so
./lib/amd64/libmanagement.so
+./lib/amd64/libnet.so
./lib/amd64/libnpt.so
./lib/amd64/libsaproc.so
./lib/amd64/libverify.so
@@ -179,6 +195,12 @@
./bin/xjc
"
+# Issue with __FILE__ usage in generated header files prevent clean fulldump diff of
+# server jvm with old hotspot build.
+KNOWN_FULLDUMP_DIFF="
+./lib/amd64/server/libjvm.so
+"
+
fi
if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
@@ -299,14 +321,13 @@
# Filter random C++ symbol strings.
# Some numbers differ randomly.
-# Can't use space in these expressions as the shell will mess with them.
DIS_DIFF_FILTER="$SED \
- -e 's/\.[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g' \
- -e 's/\([0-9a-f][0-9a-f].\)\{2,8\}[0-9a-f][0-9a-f]/<NUMS>/g' \
- -e 's/\(0x\)[0-9a-f]*\([,(>]\)/\1<HEX>\2/g' \
- -e 's/\(0x\)[0-9a-f]*$/\1<HEX>/g' \
- -e 's/\(\#.\)[0-9a-f]*\(.<\)/\1<HEX>\2/g' \
- -e 's/[\.A-Za-z0-9%]\{16,16\}$/<BIN>/g'"
+ -e 's/\.[a-zA-Z0-9_\$]\{15\}/<SYM>/g' \
+ -e 's/\(\# \)[0-9a-f]*\( <\)/\1<HEX>\2/g' \
+ -e 's/0x[0-9a-f]*$/<HEX>/g' \
+ -e 's/0x[0-9a-f]*\([,(>]\)/<HEX>\1/g' \
+ -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: <NUMS>/g' \
+ -e 's/ [\.A-Za-z0-9%@]\{16\}$/ <BIN>/g'"
fi
@@ -425,18 +446,23 @@
./bin/xjc
"
-# Filter random C++ symbol strings.
# Some numbers differ randomly.
DIS_DIFF_FILTER="$SED \
- -e 's/\$[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g' \
- -e 's/[0-9a-f][0-9a-f].[0-9a-f][0-9a-f].[0-9a-f][0-9a-f].[0-9a-f][0-9a-f]/<NUMS>/g' \
- -e 's/\(%g1,.0x\)[0-9a-f]*\(,.%g1\)/\1<HEX>\2/g' \
- -e 's/\(!.\)[0-9a-f]*\(.<SUNWprivate_1.1+0x\)[0-9a-f]*/\1<NUM>\2<HEX>/g' \
- -e 's/\!.[0-9a-f]\{1,4\} <_DYNAMIC+0x[0-9a-f]\{1,4\}>/<DYNAMIC>/g'"
+ -e 's/\$[a-zA-Z0-9_\$]\{15\}/<SYM>/g' \
+ -e 's/: [0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/: <NUMS>/g' \
+ -e 's/, [0-9a-fx\-]\{1,8\}/, <CONST>/g' \
+ -e 's/call [0-9a-f]\{7\}/call <ADDR>/g' \
+ -e 's/0x[0-9a-f]\{1,8\}/<HEX>/g' \
+ -e 's/\! [0-9a-f]\{1,8\} /! <ADDR> /g'"
-# Some xor instructions end up with different args in the lib but not in the object files.
-ACCEPTED_DIS_DIFF="
-./demo/jvmti/waiters/lib/libwaiters.so
+# libjvm.so
+# __FILE__ macro usage in debug.hpp causes differences between old and new
+# hotspot builds in ad_sparc.o and ad_sparc_clone.o. The .o files compare
+# equal when stripped, but at link time differences appear. Removing
+# __FILE__ from ShouldNotCallThis() and ShouldNotReachHere() removes
+# the differences.
+KNOWN_DIS_DIFF="
+./lib/sparcv9/server/libjvm.so
"
SKIP_FULLDUMP_DIFF="true"
@@ -634,11 +660,12 @@
SORT_SYMBOLS="
./Contents/Home/lib/libsaproc.dylib
./lib/libsaproc.dylib
+./lib/libjsig.dylib
"
ACCEPTED_SMALL_SIZE_DIFF="$ACCEPTED_BIN_DIFF"
-DIS_DIFF_FILTER="$SED \
- -e 's/0x[0-9a-f]\{4,16\}/<HEXSTR>/g'"
+DIS_DIFF_FILTER="LANG=C $SED \
+ -e 's/0x[0-9a-f]\{3,16\}/<HEXSTR>/g' -e 's/^[0-9a-f]\{12,20\}/<ADDR>/'"
fi
--- a/common/bin/jib.sh Wed Jan 06 09:39:55 2016 -0500
+++ b/common/bin/jib.sh Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
install_data=${mydir}/../../.jib/.data
setup_url() {
- if [ -f "~/.config/jib/jib.conf" ]; then
+ if [ -f ~/.config/jib/jib.conf ]; then
source ~/.config/jib/jib.conf
fi
@@ -50,6 +50,9 @@
if [ -n "${JIB_SERVER}" ]; then
jib_server="${JIB_SERVER}"
fi
+ if [ -n "${JIB_SERVER_MIRRORS}" ]; then
+ jib_server_mirrors="${JIB_SERVER_MIRRORS}"
+ fi
if [ -n "${JIB_REPOSITORY}" ]; then
jib_repository="${JIB_REPOSITORY}"
fi
@@ -70,8 +73,9 @@
jib_url="${JIB_URL}"
data_string="${jib_url}"
else
- data_string="${jib_repository}/${jib_organization}/${jib_module}/${jib_revision}/${jib_module}-${jib_revision}.${jib_ext}"
- jib_url="${jib_server}/${data_string}"
+ jib_path="${jib_repository}/${jib_organization}/${jib_module}/${jib_revision}/${jib_module}-${jib_revision}.${jib_ext}"
+ data_string="${jib_path}"
+ jib_url="${jib_server}/${jib_path}"
fi
}
@@ -104,7 +108,25 @@
${getcmd} ${jib_url} > "${installed_jib_script}.gz"
if [ ! -s "${installed_jib_script}.gz" ]; then
echo "Failed to download ${jib_url}"
- exit 1
+ if [ -n "${jib_path}" -a -n "${jib_server_mirrors}" ]; then
+ OLD_IFS="${IFS}"
+ IFS=" ,"
+ for mirror in ${jib_server_mirrors}; do
+ echo "Trying mirror ${mirror}"
+ jib_url="${mirror}/${jib_path}"
+ ${getcmd} ${jib_url} > "${installed_jib_script}.gz"
+ if [ -s "${installed_jib_script}.gz" ]; then
+ echo "Download from mirror successful"
+ break
+ else
+ echo "Failed to download ${jib_url}"
+ fi
+ done
+ IFS="${OLD_IFS}"
+ fi
+ if [ ! -s "${installed_jib_script}.gz" ]; then
+ exit 1
+ fi
fi
echo "Extracting JIB bootstrap script"
rm -f "${installed_jib_script}"
--- a/common/conf/jib-profiles.js Wed Jan 06 09:39:55 2016 -0500
+++ b/common/conf/jib-profiles.js Wed Jan 06 14:54:24 2016 +0000
@@ -357,8 +357,8 @@
var devkit_platform_revisions = {
linux_x64: "gcc4.9.2-OEL6.4+1.0",
macosx_x64: "Xcode6.3-MacOSX10.9+1.0",
- solaris_x64: "SS12u3-Solaris10u10+1.0",
- solaris_sparcv9: "SS12u3-Solaris10u10+1.0",
+ solaris_x64: "SS12u4-Solaris11u1+1.0",
+ solaris_sparcv9: "SS12u4-Solaris11u1+1.0",
windows_x64: "VS2013SP4+1.0"
};
--- a/corba/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/corba/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
fd038e8a16eec80d0d6b337d74a582790ed4b3ee jdk-9+95
feb1bd85d7990dcf5584ca9e53104269c01db006 jdk-9+96
10a482b863582376d4ca229090334b23b05159fc jdk-9+97
+ea285530245cf4e0edf0479121a41347d3030eba jdk-9+98
+180212ee1d8710691ba9944593dfc1ff3e4f1532 jdk-9+99
--- a/hotspot/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/hotspot/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -500,3 +500,5 @@
0c79cf3cdf0904fc4a630b91b32904491e1ae430 jdk-9+95
a94bb7203596dd632486f1e3655fa5f70541dc08 jdk-9+96
de592ea5f7ba0f8a8c5afc03bd169f7690c72b6f jdk-9+97
+e5b1a23be1e105417ba1c4c576ab373eb3fa2c2b jdk-9+98
+f008e8cc10d5b3212fb22d58c96fa01d38654f19 jdk-9+99
--- a/hotspot/test/runtime/logging/DefaultMethodsTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/hotspot/test/runtime/logging/DefaultMethodsTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,6 +26,7 @@
* @bug 8139564
* @summary defaultmethods=debug should have logging from each of the statements in the code
* @library /testlibrary
+ * @ignore 8146435
* @modules java.base/sun.misc
* java.management
* @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools
--- a/jaxp/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/jaxp/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
c8d0845877a811ab4350935892f826929359a3ff jdk-9+95
1f3182529f2c474e5506955ccb3820cfa5822265 jdk-9+96
9c107c050335d7ee63b2a8b38ca5d498f19713a2 jdk-9+97
+52b01339235f24c93b679bd6b8fb36a1072ad0ac jdk-9+98
+52774b544850c791f1d1c67db2601b33739b18c9 jdk-9+99
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/datatype/DurationImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -357,7 +357,7 @@
* The length of the duration in milliseconds.
*/
protected DurationImpl(final long durationInMilliSeconds) {
-
+ boolean is0x8000000000000000L = false;
long l = durationInMilliSeconds;
if (l > 0) {
@@ -368,6 +368,7 @@
if (l == 0x8000000000000000L) {
// negating 0x8000000000000000L causes an overflow
l++;
+ is0x8000000000000000L = true;
}
l *= -1;
}
@@ -406,7 +407,8 @@
// seconds & milliseconds
int2long = (gregorianCalendar.get(Calendar.SECOND) * 1000)
- + gregorianCalendar.get(Calendar.MILLISECOND);
+ + gregorianCalendar.get(Calendar.MILLISECOND)
+ + (is0x8000000000000000L ? 1 : 0);
this.seconds = BigDecimal.valueOf(int2long, 3);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/datatype/JDK8068839Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+package datatype;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/*
+ * @bug 8068839
+ * @summary Verifies that Duration's edge cases
+ */
+public class JDK8068839Test {
+
+ @Test
+ public void test() throws DatatypeConfigurationException {
+ DatatypeFactory df = DatatypeFactory.newInstance();
+ Duration durationx = df.newDuration(Long.MIN_VALUE);
+ Assert.assertEquals(durationx.toString(), "-P292277024Y7M16DT7H12M55.808S");
+ durationx = df.newDuration(Long.MAX_VALUE);
+ Assert.assertEquals(durationx.toString(), "P292277024Y7M16DT7H12M55.807S");
+ }
+
+}
--- a/jaxws/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/jaxws/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -343,3 +343,5 @@
3e03ddaaac6585fa27e91596eb2a9a31e10bdcc9 jdk-9+95
b55cebc47555293cf9c2aefb3bf63c56e847ab19 jdk-9+96
7293db4716ee25b814e14f738b9acfb85700e3fa jdk-9+97
+67c84077edc3db6b24998b35970b37c01aae985e jdk-9+98
+97b31ca0dd77483cf20ff99a033a455673639578 jdk-9+99
--- a/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/annotation/adapters/XmlAdapter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jaxws/src/java.xml.bind/share/classes/javax/xml/bind/annotation/adapters/XmlAdapter.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,10 +31,10 @@
* <p> <b> Usage: </b> </p>
*
* <p>
- * Some Java types do not map naturally to a XML representation, for
+ * Some Java types do not map naturally to an XML representation, for
* example {@code HashMap} or other non JavaBean classes. Conversely,
- * a XML repsentation may map to a Java type but an application may
- * choose to accesss the XML representation using another Java
+ * an XML representation may map to a Java type but an application may
+ * choose to access the XML representation using another Java
* type. For example, the schema to Java binding rules bind
* xs:DateTime by default to XmlGregorianCalendar. But an application
* may desire to bind xs:DateTime to a custom type,
--- a/jdk/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
8581faf0d474472e32f589bbc16db7eec912d83f jdk-9+95
c021b855f51e572e63982654b17742cb1f814fb4 jdk-9+96
fdd84b2265ddce7f50e084b7c8635189bba6f012 jdk-9+97
+f86ee68d1107dad41a27efc34306e0e56244a12e jdk-9+98
+e1a789be1535741274c9779f4d4ca3495196b5c3 jdk-9+99
--- a/jdk/make/CompileDemos.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/CompileDemos.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -309,7 +309,7 @@
ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX)
# For C++, we also need some special treatment.
- $1_LDFLAGS := $(LDFLAGS_CXX_JDK)
+ $1_LDFLAGS := $$(LDFLAGS_CXX_JDK)
$1_LIBS := $(LIBCXX)
ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
@@ -324,9 +324,9 @@
OPTIMIZATION := LOW, \
CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \
CXXFLAGS := $$($1_CXXFLAGS), \
- LDFLAGS := $(filter-out -incremental:no -opt:ref, $(LDFLAGS_JDKLIB)) \
+ LDFLAGS := $(filter-out -incremental:no -opt:ref, $$(LDFLAGS_JDKLIB)) \
$$($1_LDFLAGS), \
- LDFLAGS_macosx := $(call SET_EXECUTABLE_ORIGIN), \
+ LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN), \
LIBS := $$($1_LIBS), \
LIBS_solaris := -lc, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/jdk/make/launcher/Launcher-java.base.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/launcher/Launcher-java.base.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -127,8 +127,7 @@
$(BUILD_JEXEC_INC), \
CFLAGS_linux := -fPIC, \
CFLAGS_solaris := -KPIC, \
- LDFLAGS := $(LDFLAGS_JDKEXE) \
- $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)), \
+ LDFLAGS := $(LDFLAGS_JDKEXE), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jexec_obj, \
OUTPUT_DIR := $(BUILD_JEXEC_DST_DIR), \
DEBUG_SYMBOLS := true, \
--- a/jdk/make/launcher/Launcher-jdk.accessibility.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/launcher/Launcher-jdk.accessibility.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -73,8 +73,9 @@
$$(eval $$(call SetupNativeCompilation, BUILD_JACCESSINSPECTOR$1, \
SRC := $(TOPDIR)/jaccessinspector $(TOPDIR)/common \
$(TOPDIR)/toolscommon $(TOPDIR)/include/bridge, \
- CFLAGS := $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 /EHsc, \
- LDFLAGS := $$(LDFLAGS_JDKEXE) /STACK:655360 Advapi32.lib User32.lib, \
+ CFLAGS := $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 -EHsc, \
+ LDFLAGS := $$(LDFLAGS_JDKEXE) -stack:655360, \
+ LIBS := advapi32.lib user32.lib, \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/jdk.accessibility/jaccessinspector$1, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/jdk.accessibility, \
PROGRAM := jaccessinspector$1, \
@@ -100,8 +101,9 @@
$$(eval $$(call SetupNativeCompilation,BUILD_JACCESSWALKER$1, \
SRC := $(TOPDIR)/jaccesswalker $(TOPDIR)/common \
$(TOPDIR)/toolscommon $(TOPDIR)/include/bridge, \
- CFLAGS :== $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 /EHsc, \
- LDFLAGS := $$(LDFLAGS_JDKEXE) /STACK:655360 Advapi32.lib Comctl32.lib Gdi32.lib User32.lib, \
+ CFLAGS := $$(CFLAGS_JDKEXE) $(TOOLS_CFLAGS) -DACCESSBRIDGE_ARCH_$2 -EHsc, \
+ LDFLAGS := $$(LDFLAGS_JDKEXE) -stack:655360, \
+ LIBS := advapi32.lib comctl32.lib gdi32.lib user32.lib, \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/jdk.accessibility/jaccesswalker$1, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/jdk.accessibility, \
PROGRAM := jaccesswalker$1, \
--- a/jdk/make/launcher/Launcher-jdk.pack200.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/launcher/Launcher-jdk.pack200.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -89,7 +89,6 @@
MAPFILE := $(UNPACK_MAPFILE),\
LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
$(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
- $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX)) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(UNPACKEXE_LIBS) $(LIBCXX), \
LIBS_solaris := -lc, \
--- a/jdk/make/launcher/LauncherCommon.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/launcher/LauncherCommon.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,12 @@
include NativeCompilation.gmk
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk binaries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+ ENABLE_DEBUG_SYMBOLS := false
+endif
+
# Prepare the find cache.
$(eval $(call FillCacheFind, $(JDK_TOPDIR)/src/java.base/share/native/launcher))
@@ -180,15 +186,12 @@
CFLAGS_linux := -fPIC, \
CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \
CFLAGS_windows := $$($1_CFLAGS_windows), \
- LDFLAGS := $(LDFLAGS_JDKEXE) \
+ LDFLAGS := $$(LDFLAGS_JDKEXE) \
$$(ORIGIN_ARG) \
$$($1_LDFLAGS), \
LDFLAGS_linux := \
- $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
- LDFLAGS_macosx := $(call SET_SHARED_LIBRARY_NAME,$1), \
LDFLAGS_solaris := $$($1_LDFLAGS_solaris) \
- $(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)$(SHARED_LIBRARY_SUFFIX)) \
-L$(SUPPORT_OUTPUTDIR)/modules_libs/java.base$(OPENJDK_TARGET_CPU_LIBDIR)/jli, \
MAPFILE := $$($1_MAPFILE), \
LIBS := $(JDKEXE_LIBS) $$($1_LIBS), \
--- a/jdk/make/lib/Awt2dLibraries.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/lib/Awt2dLibraries.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -683,7 +683,7 @@
WARNINGS_AS_ERRORS_gcc := false, \
WARNINGS_AS_ERRORS_solstudio := false, \
MAPFILE := $(BUILD_LIBFONTMANAGER_MAPFILE), \
- LDFLAGS := $(subst -Xlinker -z -Xlinker defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
+ LDFLAGS := $(subst -Wl$(COMMA)-z$(COMMA)defs,,$(LDFLAGS_JDKLIB)) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
LDFLAGS_macosx := -undefined dynamic_lookup, \
@@ -799,7 +799,7 @@
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_unix := -L$(INSTALL_LIBRARIES_HERE), \
- LDFLAGS_macosx := -Xlinker -rpath -Xlinker @loader_path, \
+ LDFLAGS_macosx := -Wl$(COMMA)-rpath$(COMMA)@loader_path, \
LIBS_unix := $(JAWT_LIBS) $(JDKLIB_LIBS), \
LIBS_solaris := $(X_LIBS) -lXrender, \
LIBS_macosx := -framework Cocoa, \
@@ -1034,7 +1034,7 @@
-I$(SUPPORT_OUTPUTDIR)/headers/java.desktop, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN) \
- -Xlinker -rpath -Xlinker @loader_path \
+ -Wl$(COMMA)-rpath$(COMMA)@loader_path \
-L$(INSTALL_LIBRARIES_HERE), \
LIBS := -lawt -losxapp -lawt_lwawt \
-framework Cocoa \
--- a/jdk/make/lib/Lib-java.instrument.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/lib/Lib-java.instrument.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -65,7 +65,7 @@
-L$(call FindLibDirForModule, java.base)/jli, \
LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/jli) \
-L$(call FindLibDirForModule, java.base)/jli, \
- LDFLAGS_macosx := -Xlinker -all_load $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
+ LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
LDFLAGS_windows := -export:Agent_OnAttach, \
LIBS := $(JDKLIB_LIBS), \
@@ -74,7 +74,8 @@
LIBS_solaris := -ljli $(LIBDL), \
LIBS_aix := -liconv -ljli_static $(LIBDL), \
LIBS_macosx := -liconv -framework Cocoa -framework Security \
- -framework ApplicationServices, \
+ -framework ApplicationServices \
+ $(SUPPORT_OUTPUTDIR)/native/java.base/libjli_static.a, \
LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib \
$(SUPPORT_OUTPUTDIR)/native/java.base/jli_static.lib, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
--- a/jdk/make/lib/LibCommon.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/lib/LibCommon.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -46,6 +46,12 @@
endif
endif
+# SetupNativeCompilation now supports debug symbols on macosx for hotspot.
+# Disable it here for the jdk libraries until we decide to enable them.
+ifeq ($(OPENJDK_TARGET_OS), macosx)
+ ENABLE_DEBUG_SYMBOLS := false
+endif
+
################################################################################
# Find the default set of src dirs for a native library.
# Param 1 - module name
--- a/jdk/make/mapfiles/libzip/mapfile-vers Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/mapfiles/libzip/mapfile-vers Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 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
@@ -27,7 +27,6 @@
SUNWprivate_1.1 {
global:
- Java_java_util_jar_JarFile_getMetaInfEntryNames;
Java_java_util_zip_Adler32_update;
Java_java_util_zip_Adler32_updateBytes;
Java_java_util_zip_Adler32_updateByteBuffer;
@@ -48,25 +47,6 @@
Java_java_util_zip_Inflater_initIDs;
Java_java_util_zip_Inflater_reset;
Java_java_util_zip_Inflater_setDictionary;
- Java_java_util_zip_ZipFile_close;
- Java_java_util_zip_ZipFile_getCommentBytes;
- Java_java_util_zip_ZipFile_freeEntry;
- Java_java_util_zip_ZipFile_getEntry;
- Java_java_util_zip_ZipFile_getEntryBytes;
- Java_java_util_zip_ZipFile_getEntryCrc;
- Java_java_util_zip_ZipFile_getEntryCSize;
- Java_java_util_zip_ZipFile_getEntryFlag;
- Java_java_util_zip_ZipFile_getEntryMethod;
- Java_java_util_zip_ZipFile_getEntrySize;
- Java_java_util_zip_ZipFile_getEntryTime;
- Java_java_util_zip_ZipFile_getNextEntry;
- Java_java_util_zip_ZipFile_getZipMessage;
- Java_java_util_zip_ZipFile_getTotal;
- Java_java_util_zip_ZipFile_initIDs;
- Java_java_util_zip_ZipFile_open;
- Java_java_util_zip_ZipFile_read;
- Java_java_util_zip_ZipFile_startsWithLOC;
-
ZIP_Close;
ZIP_CRC32;
ZIP_FindEntry;
--- a/jdk/make/mapfiles/libzip/reorder-sparc Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/mapfiles/libzip/reorder-sparc Wed Jan 06 14:54:24 2016 +0000
@@ -16,30 +16,14 @@
text: .text%ZIP_Lock;
text: .text%ZIP_Unlock;
text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
text: .text%zcalloc;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
-text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%zcfree;
-text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%Java_java_util_zip_Inflater_reset;
text: .text%Java_java_util_zip_Inflater_end;
text: .text%inflateEnd;
-text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
--- a/jdk/make/mapfiles/libzip/reorder-sparcv9 Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/mapfiles/libzip/reorder-sparcv9 Wed Jan 06 14:54:24 2016 +0000
@@ -15,19 +15,6 @@
text: .text%ZIP_Lock;
text: .text%ZIP_Unlock;
text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
text: .text%Java_java_util_zip_Inflater_initIDs;
text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
@@ -35,7 +22,6 @@
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
-text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%zcfree;
text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
@@ -43,6 +29,5 @@
text: .text%InflateFully;
text: .text%inflateEnd;
text: .text%Java_java_util_zip_Inflater_reset;
-text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
text: .text%Java_java_util_zip_Inflater_end;
--- a/jdk/make/mapfiles/libzip/reorder-x86 Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/make/mapfiles/libzip/reorder-x86 Wed Jan 06 14:54:24 2016 +0000
@@ -16,34 +16,16 @@
text: .text%ZIP_Lock;
text: .text%ZIP_Unlock;
text: .text%ZIP_FreeEntry;
-text: .text%Java_java_util_zip_ZipFile_initIDs;
-text: .text%Java_java_util_zip_ZipFile_open;
-text: .text%Java_java_util_zip_ZipFile_getTotal;
-text: .text%Java_java_util_zip_ZipFile_startsWithLOC;
-text: .text%Java_java_util_zip_ZipFile_getEntry;
-text: .text%Java_java_util_zip_ZipFile_freeEntry;
-text: .text%Java_java_util_zip_ZipFile_getEntryTime;
-text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
-text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
-text: .text%Java_java_util_zip_ZipFile_getEntrySize;
-text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
-text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
-text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
-text: .text%Java_java_util_zip_Inflater_initIDs;
-text: .text%Java_java_util_zip_Inflater_init;
text: .text%inflateInit2_;
text: .text%zcalloc;
text: .text%inflateReset;
text: .text%Java_java_util_zip_Inflater_inflateBytes;
text: .text%inflate;
-text: .text%Java_java_util_zip_ZipFile_read;
text: .text%ZIP_Read;
text: .text%zcfree;
-text: .text%Java_java_util_jar_JarFile_getMetaInfEntryNames;
text: .text%ZIP_ReadEntry;
text: .text%InflateFully;
text: .text%inflateEnd;
text: .text%Java_java_util_zip_Inflater_reset;
-text: .text%Java_java_util_zip_ZipFile_close;
text: .text%ZIP_Close;
text: .text%Java_java_util_zip_Inflater_end;
--- a/jdk/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,6 @@
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
-import sun.misc.*;
/**
* An implementation of Selector for Linux 2.6+ kernels that uses
@@ -50,7 +49,7 @@
private Map<Integer,SelectionKeyImpl> fdToKey;
// True if this Selector has been closed
- private volatile boolean closed = false;
+ private volatile boolean closed;
// Lock for interrupt triggering and clearing
private final Object interruptLock = new Object();
--- a/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java Wed Jan 06 14:54:24 2016 +0000
@@ -322,19 +322,6 @@
bytesRead = 0;
}
- // process any pending requests
- if ((nReady > 1) || (nReady == 1 && bytesRead == 0)) {
- try {
- read(socketpair[0], address, BUFFER_SIZE);
- boolean shutdown = processRequests();
- if (shutdown)
- break;
- } catch (UnixException x) {
- if (x.errno() != UnixConstants.EAGAIN)
- throw x;
- }
- }
-
// iterate over buffer to decode events
int offset = 0;
while (offset < bytesRead) {
@@ -369,6 +356,19 @@
offset += (SIZEOF_INOTIFY_EVENT + len);
}
+
+ // process any pending requests
+ if ((nReady > 1) || (nReady == 1 && bytesRead == 0)) {
+ try {
+ read(socketpair[0], address, BUFFER_SIZE);
+ boolean shutdown = processRequests();
+ if (shutdown)
+ break;
+ } catch (UnixException x) {
+ if (x.errno() != UnixConstants.EAGAIN)
+ throw x;
+ }
+ }
}
} catch (UnixException x) {
x.printStackTrace();
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/BlockCipherParamsCore.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,7 +27,7 @@
import java.io.*;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.IvParameterSpec;
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/GCMParameters.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.GCMParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBEParameters.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,7 @@
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.PBEParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PBES2Parameters.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/RC2Parameters.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.spec.RC2ParameterSpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java Wed Jan 06 14:54:24 2016 +0000
@@ -93,7 +93,7 @@
// Instance of this provider, so we don't have to call the provider list
// to find ourselves or run the risk of not being in the list.
- private static volatile SunJCE instance = null;
+ private static volatile SunJCE instance;
// lazy initialize SecureRandom to avoid potential recursion if Sun
// provider has not been installed yet
--- a/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java Wed Jan 06 14:54:24 2016 +0000
@@ -118,7 +118,7 @@
public void debug(byte[] bytes) {
if (DEBUG) {
try {
- new sun.misc.HexDumpEncoder().encodeBuffer(bytes, System.out);
+ new sun.security.util.HexDumpEncoder().encodeBuffer(bytes, System.out);
} catch (IOException ioe) {
// Impossible
}
--- a/jdk/src/java.base/share/classes/java/io/CharArrayReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/io/CharArrayReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -225,9 +225,12 @@
* Closes the stream and releases any system resources associated with
* it. Once the stream has been closed, further read(), ready(),
* mark(), reset(), or skip() invocations will throw an IOException.
- * Closing a previously closed stream has no effect.
+ * Closing a previously closed stream has no effect. This method will block
+ * while there is another thread blocking on the reader.
*/
public void close() {
- buf = null;
+ synchronized (lock) {
+ buf = null;
+ }
}
}
--- a/jdk/src/java.base/share/classes/java/io/File.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/io/File.java Wed Jan 06 14:54:24 2016 +0000
@@ -420,11 +420,11 @@
String scheme = uri.getScheme();
if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
throw new IllegalArgumentException("URI scheme is not \"file\"");
- if (uri.getAuthority() != null)
+ if (uri.getRawAuthority() != null)
throw new IllegalArgumentException("URI has an authority component");
- if (uri.getFragment() != null)
+ if (uri.getRawFragment() != null)
throw new IllegalArgumentException("URI has a fragment component");
- if (uri.getQuery() != null)
+ if (uri.getRawQuery() != null)
throw new IllegalArgumentException("URI has a query component");
String p = uri.getPath();
if (p.equals(""))
--- a/jdk/src/java.base/share/classes/java/io/PipedInputStream.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/io/PipedInputStream.java Wed Jan 06 14:54:24 2016 +0000
@@ -48,9 +48,9 @@
* @since 1.0
*/
public class PipedInputStream extends InputStream {
- boolean closedByWriter = false;
- volatile boolean closedByReader = false;
- boolean connected = false;
+ boolean closedByWriter;
+ volatile boolean closedByReader;
+ boolean connected;
/* REMIND: identification of the read and write sides needs to be
more sophisticated. Either using thread groups (but what about
--- a/jdk/src/java.base/share/classes/java/io/PushbackReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/io/PushbackReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -241,13 +241,16 @@
* Closes the stream and releases any system resources associated with
* it. Once the stream has been closed, further read(),
* unread(), ready(), or skip() invocations will throw an IOException.
- * Closing a previously closed stream has no effect.
+ * Closing a previously closed stream has no effect. This method will block
+ * while there is another thread blocking on the reader.
*
* @exception IOException If an I/O error occurs
*/
public void close() throws IOException {
- super.close();
- buf = null;
+ synchronized (lock) {
+ super.close();
+ buf = null;
+ }
}
/**
--- a/jdk/src/java.base/share/classes/java/io/StringReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/io/StringReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -194,9 +194,12 @@
* Closes the stream and releases any system resources associated with
* it. Once the stream has been closed, further read(),
* ready(), mark(), or reset() invocations will throw an IOException.
- * Closing a previously closed stream has no effect.
+ * Closing a previously closed stream has no effect. This method will block
+ * while there is another thread blocking on the reader.
*/
public void close() {
- str = null;
+ synchronized (lock) {
+ str = null;
+ }
}
}
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,7 +25,7 @@
package java.lang;
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
import java.util.Arrays;
import java.util.Spliterator;
import java.util.stream.IntStream;
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java Wed Jan 06 14:54:24 2016 +0000
@@ -2518,7 +2518,7 @@
// Incremented by the VM on each call to JVM TI RedefineClasses()
// that redefines this class or a superclass.
- private transient volatile int classRedefinedCount = 0;
+ private transient volatile int classRedefinedCount;
// Lazily create and cache ReflectionData
private ReflectionData<T> reflectionData() {
@@ -3331,7 +3331,8 @@
* uncloned, cached, and shared by all callers.
*/
T[] getEnumConstantsShared() {
- if (enumConstants == null) {
+ T[] constants = enumConstants;
+ if (constants == null) {
if (!isEnum()) return null;
try {
final Method values = getMethod("values");
@@ -3344,16 +3345,16 @@
});
@SuppressWarnings("unchecked")
T[] temporaryConstants = (T[])values.invoke(null);
- enumConstants = temporaryConstants;
+ enumConstants = constants = temporaryConstants;
}
// These can happen when users concoct enum-like classes
// that don't comply with the enum spec.
catch (InvocationTargetException | NoSuchMethodException |
IllegalAccessException ex) { return null; }
}
- return enumConstants;
+ return constants;
}
- private transient volatile T[] enumConstants = null;
+ private transient volatile T[] enumConstants;
/**
* Returns a map from simple name to enum constant. This package-private
@@ -3363,19 +3364,21 @@
* created lazily on first use. Typically it won't ever get created.
*/
Map<String, T> enumConstantDirectory() {
- if (enumConstantDirectory == null) {
+ Map<String, T> directory = enumConstantDirectory;
+ if (directory == null) {
T[] universe = getEnumConstantsShared();
if (universe == null)
throw new IllegalArgumentException(
getName() + " is not an enum type");
- Map<String, T> m = new HashMap<>(2 * universe.length);
- for (T constant : universe)
- m.put(((Enum<?>)constant).name(), constant);
- enumConstantDirectory = m;
+ directory = new HashMap<>(2 * universe.length);
+ for (T constant : universe) {
+ directory.put(((Enum<?>)constant).name(), constant);
+ }
+ enumConstantDirectory = directory;
}
- return enumConstantDirectory;
+ return directory;
}
- private transient volatile Map<String, T> enumConstantDirectory = null;
+ private transient volatile Map<String, T> enumConstantDirectory;
/**
* Casts an object to the class or interface represented
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed Jan 06 14:54:24 2016 +0000
@@ -45,11 +45,11 @@
import java.util.Set;
import java.util.Stack;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Vector;
import java.util.Hashtable;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
-import sun.misc.CompoundEnumeration;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.reflect.CallerSensitive;
@@ -2206,3 +2206,36 @@
return sys;
}
}
+
+/*
+ * A utility class that will enumerate over an array of enumerations.
+ */
+final class CompoundEnumeration<E> implements Enumeration<E> {
+ private final Enumeration<E>[] enums;
+ private int index;
+
+ public CompoundEnumeration(Enumeration<E>[] enums) {
+ this.enums = enums;
+ }
+
+ private boolean next() {
+ while (index < enums.length) {
+ if (enums[index] != null && enums[index].hasMoreElements()) {
+ return true;
+ }
+ index++;
+ }
+ return false;
+ }
+
+ public boolean hasMoreElements() {
+ return next();
+ }
+
+ public E nextElement() {
+ if (!next()) {
+ throw new NoSuchElementException();
+ }
+ return enums[index].nextElement();
+ }
+}
--- a/jdk/src/java.base/share/classes/java/lang/Double.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/Double.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,8 +25,8 @@
package java.lang;
-import sun.misc.FloatingDecimal;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/Float.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/Float.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,9 +25,9 @@
package java.lang;
-import sun.misc.FloatingDecimal;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatingDecimal;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/InheritableThreadLocal.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/InheritableThreadLocal.java Wed Jan 06 14:54:24 2016 +0000
@@ -40,6 +40,11 @@
* maintained in the variable (e.g., User ID, Transaction ID) must be
* automatically transmitted to any child threads that are created.
*
+ * <p>Note: During the creation of a new {@link
+ * Thread#Thread(ThreadGroup,Runnable,String,long,boolean) thread}, it is
+ * possible to <i>opt out</i> of receiving initial values for inheritable
+ * thread-local variables.
+ *
* @author Josh Bloch and Doug Lea
* @see ThreadLocal
* @since 1.2
--- a/jdk/src/java.base/share/classes/java/lang/Math.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,8 +26,8 @@
package java.lang;
import java.util.Random;
-import sun.misc.FloatConsts;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.FloatConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/StackWalker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/StackWalker.java Wed Jan 06 14:54:24 2016 +0000
@@ -304,8 +304,8 @@
}
/**
- * Returns a {@code StackWalker} instance with the given {@ocde options} specifying
- * the stack frame information it can access. If the given {@ocde options}
+ * Returns a {@code StackWalker} instance with the given {@code options} specifying
+ * the stack frame information it can access. If the given {@code options}
* is empty, this {@code StackWalker} is configured to skip all
* {@linkplain Option#SHOW_HIDDEN_FRAMES hidden frames} and no
* {@linkplain Option#RETAIN_CLASS_REFERENCE class reference} is retained.
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,7 +26,7 @@
package java.lang;
import java.util.Random;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java Wed Jan 06 14:54:24 2016 +0000
@@ -120,7 +120,8 @@
public static byte[] toBytes(char[] value, int off, int len) {
byte[] val = newBytesFor(len);
for (int i = 0; i < len; i++) {
- putChar(val, i, value[off++]);
+ putChar(val, i, value[off]);
+ off++;
}
return val;
}
@@ -145,11 +146,14 @@
@HotSpotIntrinsicCandidate
private static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
for (int i = 0; i < len; i++) {
- int c = src[srcOff++];
- if (c >>> 8 != 0) {
- return 0;
+ char c = src[srcOff];
+ if (c > 0xFF) {
+ len = 0;
+ break;
}
- dst[dstOff++] = (byte)c;
+ dst[dstOff] = (byte)c;
+ srcOff++;
+ dstOff++;
}
return len;
}
@@ -160,11 +164,14 @@
// We need a range check here because 'getChar' has no checks
checkBoundsOffCount(srcOff, len, src.length);
for (int i = 0; i < len; i++) {
- int c = getChar(src, srcOff++);
- if (c >>> 8 != 0) {
- return 0;
+ char c = getChar(src, srcOff);
+ if (c > 0xFF) {
+ len = 0;
+ break;
}
- dst[dstOff++] = (byte)c;
+ dst[dstOff] = (byte)c;
+ srcOff++;
+ dstOff++;
}
return len;
}
@@ -581,7 +588,7 @@
bits |= cp;
putChar(result, i, cp);
}
- if (bits >>> 8 != 0) {
+ if (bits > 0xFF) {
return new String(result, UTF16);
} else {
return newString(result, 0, len);
@@ -678,7 +685,7 @@
bits |= cp;
putChar(result, i, cp);
}
- if (bits >>> 8 != 0) {
+ if (bits > 0xFF) {
return new String(result, UTF16);
} else {
return newString(result, 0, len);
--- a/jdk/src/java.base/share/classes/java/lang/System.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/System.java Wed Jan 06 14:54:24 2016 +0000
@@ -132,7 +132,7 @@
/* The security manager for the system.
*/
- private static volatile SecurityManager security = null;
+ private static volatile SecurityManager security;
/**
* Reassigns the "standard" input stream.
@@ -206,7 +206,7 @@
setErr0(err);
}
- private static volatile Console cons = null;
+ private static volatile Console cons;
/**
* Returns the unique {@link java.io.Console Console} object associated
* with the current Java virtual machine, if any.
@@ -216,12 +216,13 @@
* @since 1.6
*/
public static Console console() {
- if (cons == null) {
+ Console c = cons;
+ if (c == null) {
synchronized (System.class) {
- cons = SharedSecrets.getJavaIOAccess().console();
+ cons = c = SharedSecrets.getJavaIOAccess().console();
}
}
- return cons;
+ return c;
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/Thread.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/Thread.java Wed Jan 06 14:54:24 2016 +0000
@@ -207,12 +207,10 @@
/* For generating thread ID */
private static long threadSeqNumber;
- /* Java thread status for tools,
- * initialized to indicate thread 'not yet started'
+ /*
+ * Java thread status for tools, default indicates thread 'not yet started'
*/
-
- private volatile int threadStatus = 0;
-
+ private volatile int threadStatus;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
@@ -344,11 +342,11 @@
/**
* Initializes a Thread with the current AccessControlContext.
- * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext)
+ * @see #init(ThreadGroup,Runnable,String,long,AccessControlContext,boolean)
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
- init(g, target, name, stackSize, null);
+ init(g, target, name, stackSize, null, true);
}
/**
@@ -361,9 +359,12 @@
* zero to indicate that this parameter is to be ignored.
* @param acc the AccessControlContext to inherit, or
* AccessController.getContext() if null
+ * @param inheritThreadLocals if {@code true}, inherit initial values for
+ * inheritable thread-locals from the constructing thread
*/
private void init(ThreadGroup g, Runnable target, String name,
- long stackSize, AccessControlContext acc) {
+ long stackSize, AccessControlContext acc,
+ boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
@@ -414,7 +415,7 @@
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
- if (parent.inheritableThreadLocals != null)
+ if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
@@ -468,7 +469,7 @@
* This is not a public constructor.
*/
Thread(Runnable target, AccessControlContext acc) {
- init(null, target, "Thread-" + nextThreadNum(), 0, acc);
+ init(null, target, "Thread-" + nextThreadNum(), 0, acc, true);
}
/**
@@ -678,6 +679,62 @@
}
/**
+ * Allocates a new {@code Thread} object so that it has {@code target}
+ * as its run object, has the specified {@code name} as its name,
+ * belongs to the thread group referred to by {@code group}, has
+ * the specified {@code stackSize}, and inherits initial values for
+ * {@linkplain InheritableThreadLocal inheritable thread-local} variables
+ * if {@code inheritThreadLocals} is {@code true}.
+ *
+ * <p> This constructor is identical to {@link
+ * #Thread(ThreadGroup,Runnable,String,long)} with the added ability to
+ * suppress, or not, the inheriting of initial values for inheritable
+ * thread-local variables from the constructing thread. This allows for
+ * finer grain control over inheritable thread-locals. Care must be taken
+ * when passing a value of {@code false} for {@code inheritThreadLocals},
+ * as it may lead to unexpected behavior if the new thread executes code
+ * that expects a specific thread-local value to be inherited.
+ *
+ * <p> Specifying a value of {@code true} for the {@code inheritThreadLocals}
+ * parameter will cause this constructor to behave exactly like the
+ * {@code Thread(ThreadGroup, Runnable, String, long)} constructor.
+ *
+ * @param group
+ * the thread group. If {@code null} and there is a security
+ * manager, the group is determined by {@linkplain
+ * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
+ * If there is not a security manager or {@code
+ * SecurityManager.getThreadGroup()} returns {@code null}, the group
+ * is set to the current thread's thread group.
+ *
+ * @param target
+ * the object whose {@code run} method is invoked when this thread
+ * is started. If {@code null}, this thread's run method is invoked.
+ *
+ * @param name
+ * the name of the new thread
+ *
+ * @param stackSize
+ * the desired stack size for the new thread, or zero to indicate
+ * that this parameter is to be ignored
+ *
+ * @param inheritThreadLocals
+ * if {@code true}, inherit initial values for inheritable
+ * thread-locals from the constructing thread, otherwise no initial
+ * values are inherited
+ *
+ * @throws SecurityException
+ * if the current thread cannot create a thread in the specified
+ * thread group
+ *
+ * @since 9
+ */
+ public Thread(ThreadGroup group, Runnable target, String name,
+ long stackSize, boolean inheritThreadLocals) {
+ init(group, target, name, stackSize, null, inheritThreadLocals);
+ }
+
+ /**
* Causes this thread to begin execution; the Java Virtual Machine
* calls the <code>run</code> method of this thread.
* <p>
--- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java Wed Jan 06 14:54:24 2016 +0000
@@ -83,7 +83,6 @@
*/
abstract
public class CallSite {
- static { MethodHandleImpl.initStatics(); }
// The actual payload of this call site:
/*package-private*/
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java Wed Jan 06 14:54:24 2016 +0000
@@ -1073,11 +1073,6 @@
}
}
-// static {
-// System.out.println("Hello world! My methods are:");
-// System.out.println(Factory.INSTANCE.getMethods(MemberName.class, true, null));
-// }
-
static {
// Allow privileged classes outside of java.lang
jdk.internal.misc.SharedSecrets.setJavaLangInvokeAccess(new jdk.internal.misc.JavaLangInvokeAccess() {
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java Wed Jan 06 14:54:24 2016 +0000
@@ -420,7 +420,6 @@
* @author John Rose, JSR 292 EG
*/
public abstract class MethodHandle {
- static { MethodHandleImpl.initStatics(); }
/**
* Internal marker interface which distinguishes (to the Java compiler)
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.function.Function;
-import java.util.stream.Collectors;
import sun.invoke.empty.Empty;
import sun.invoke.util.ValueConversions;
@@ -65,11 +64,6 @@
/// Factory methods to create method handles:
- static void initStatics() {
- // Trigger selected static initializations.
- MemberName.Factory.INSTANCE.getClass();
- }
-
static MethodHandle makeArrayElementAccessor(Class<?> arrayClass, boolean isSetter) {
if (arrayClass == Object[].class)
return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER);
@@ -700,33 +694,43 @@
MethodHandle makeBlockInliningWrapper(MethodHandle target) {
LambdaForm lform;
if (DONT_INLINE_THRESHOLD > 0) {
- lform = PRODUCE_BLOCK_INLINING_FORM.apply(target);
+ lform = Makers.PRODUCE_BLOCK_INLINING_FORM.apply(target);
} else {
- lform = PRODUCE_REINVOKER_FORM.apply(target);
+ lform = Makers.PRODUCE_REINVOKER_FORM.apply(target);
}
return new CountingWrapper(target, lform,
- PRODUCE_BLOCK_INLINING_FORM, PRODUCE_REINVOKER_FORM,
+ Makers.PRODUCE_BLOCK_INLINING_FORM, Makers.PRODUCE_REINVOKER_FORM,
DONT_INLINE_THRESHOLD);
}
- /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */
- private static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
- @Override
- public LambdaForm apply(MethodHandle target) {
- return DelegatingMethodHandle.makeReinvokerForm(target,
- MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false,
- DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
- }
- };
+ private final static class Makers {
+ /** Constructs reinvoker lambda form which block inlining during JIT-compilation for a particular method handle */
+ static final Function<MethodHandle, LambdaForm> PRODUCE_BLOCK_INLINING_FORM = new Function<MethodHandle, LambdaForm>() {
+ @Override
+ public LambdaForm apply(MethodHandle target) {
+ return DelegatingMethodHandle.makeReinvokerForm(target,
+ MethodTypeForm.LF_DELEGATE_BLOCK_INLINING, CountingWrapper.class, "reinvoker.dontInline", false,
+ DelegatingMethodHandle.NF_getTarget, CountingWrapper.NF_maybeStopCounting);
+ }
+ };
- /** Constructs simple reinvoker lambda form for a particular method handle */
- private static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
- @Override
- public LambdaForm apply(MethodHandle target) {
- return DelegatingMethodHandle.makeReinvokerForm(target,
- MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
- }
- };
+ /** Constructs simple reinvoker lambda form for a particular method handle */
+ static final Function<MethodHandle, LambdaForm> PRODUCE_REINVOKER_FORM = new Function<MethodHandle, LambdaForm>() {
+ @Override
+ public LambdaForm apply(MethodHandle target) {
+ return DelegatingMethodHandle.makeReinvokerForm(target,
+ MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, DelegatingMethodHandle.NF_getTarget);
+ }
+ };
+
+ /** Maker of type-polymorphic varargs */
+ static final ClassValue<MethodHandle[]> TYPED_COLLECTORS = new ClassValue<MethodHandle[]>() {
+ @Override
+ protected MethodHandle[] computeValue(Class<?> type) {
+ return new MethodHandle[MAX_JVM_ARITY + 1];
+ }
+ };
+ }
/**
* Counting method handle. It has 2 states: counting and non-counting.
@@ -1527,15 +1531,6 @@
return MethodHandles.collectArguments(rightFill, 0, midFill);
}
- // Type-polymorphic version of varargs maker.
- private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS
- = new ClassValue<MethodHandle[]>() {
- @Override
- protected MethodHandle[] computeValue(Class<?> type) {
- return new MethodHandle[256];
- }
- };
-
static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM
/** Return a method handle that takes the indicated number of
@@ -1557,7 +1552,7 @@
if (elemType == Object.class)
return varargsArray(nargs);
// other cases: primitive arrays, subtypes of Object[]
- MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
+ MethodHandle cache[] = Makers.TYPED_COLLECTORS.get(elemType);
MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
if (mh != null) return mh;
if (nargs == 0) {
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java Wed Jan 06 14:54:24 2016 +0000
@@ -87,9 +87,6 @@
private static native void registerNatives();
static {
registerNatives();
-
- // The JVM calls MethodHandleNatives.<clinit>. Cascade the <clinit> calls as needed:
- MethodHandleImpl.initStatics();
}
/**
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java Wed Jan 06 14:54:24 2016 +0000
@@ -61,7 +61,7 @@
private MethodHandles() { } // do not instantiate
private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
- static { MethodHandleImpl.initStatics(); }
+
// See IMPL_LOOKUP below.
//// Method handle creation from ordinary methods.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,231 @@
+/*
+ * 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 java.lang.ref;
+
+import java.util.Objects;
+import java.util.concurrent.ThreadFactory;
+
+import jdk.internal.misc.CleanerImpl;
+
+/**
+ * {@code Cleaner} manages a set of object references and corresponding cleaning actions.
+ * <p>
+ * Cleaning actions are {@link #register(Object object, Runnable action) registered}
+ * to run after the cleaner is notified that the object has become
+ * phantom reachable.
+ * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be
+ * notified when the <a href="package-summary.html#reachability">reachability</a>
+ * changes.
+ * <p>
+ * Each cleaner operates independently, managing the pending cleaning actions
+ * and handling threading and termination when the cleaner is no longer in use.
+ * Registering an object reference and corresponding cleaning action returns
+ * a {@link Cleanable Cleanable}. The most efficient use is to explicitly invoke
+ * the {@link Cleanable#clean clean} method when the object is closed or
+ * no longer needed.
+ * The cleaning action is a {@link Runnable} to be invoked at most once when
+ * the object has become phantom reachable unless it has already been explicitly cleaned.
+ * Note that the cleaning action must not refer to the object being registered.
+ * If so, the object will not become phantom reachable and the cleaning action
+ * will not be invoked automatically.
+ * <p>
+ * The execution of the cleaning action is performed
+ * by a thread associated with the cleaner.
+ * All exceptions thrown by the cleaning action are ignored.
+ * The cleaner and other cleaning actions are not affected by
+ * exceptions in a cleaning action.
+ * The thread runs until all registered cleaning actions have
+ * completed and the cleaner itself is reclaimed by the garbage collector.
+ * <p>
+ * The behavior of cleaners during {@link System#exit(int) System.exit}
+ * is implementation specific. No guarantees are made relating
+ * to whether cleaning actions are invoked or not.
+ * <p>
+ * Unless otherwise noted, passing a {@code null} argument to a constructor or
+ * method in this class will cause a
+ * {@link java.lang.NullPointerException NullPointerException} to be thrown.
+ *
+ * @apiNote
+ * The cleaning action is invoked only after the associated object becomes
+ * phantom reachable, so it is important that the object implementing the
+ * cleaning action does not hold references to the object.
+ * In this example, a static class encapsulates the cleaning state and action.
+ * An "inner" class, anonymous or not, must not be used because it implicitly
+ * contains a reference to the outer instance, preventing it from becoming
+ * phantom reachable.
+ * The choice of a new cleaner or sharing an existing cleaner is determined
+ * by the use case.
+ * <p>
+ * If the CleaningExample is used in a try-finally block then the
+ * {@code close} method calls the cleaning action.
+ * If the {@code close} method is not called, the cleaning action is called
+ * by the Cleaner when the CleaningExample instance has become phantom reachable.
+ * <pre>{@code
+ * public class CleaningExample implements AutoCloseable {
+ * // A cleaner, preferably one shared within a library
+ * private static final Cleaner cleaner = <cleaner>;
+ *
+ * static class State implements Runnable {
+ *
+ * State(...) {
+ * // initialize State needed for cleaning action
+ * }
+ *
+ * public void run() {
+ * // cleanup action accessing State, executed at most once
+ * }
+ * }
+ *
+ * private final State;
+ * private final Cleaner.Cleanable cleanable
+ *
+ * public CleaningExample() {
+ * this.state = new State(...);
+ * this.cleanable = cleaner.register(this, state);
+ * }
+ *
+ * public void close() {
+ * cleanable.clean();
+ * }
+ * }
+ * }</pre>
+ * The cleaning action could be a lambda but all too easily will capture
+ * the object reference, by referring to fields of the object being cleaned,
+ * preventing the object from becoming phantom reachable.
+ * Using a static nested class, as above, will avoid accidentally retaining the
+ * object reference.
+ * <p>
+ * <a name="compatible-cleaners"></a>
+ * Cleaning actions should be prepared to be invoked concurrently with
+ * other cleaning actions.
+ * Typically the cleaning actions should be very quick to execute
+ * and not block. If the cleaning action blocks, it may delay processing
+ * other cleaning actions registered to the same cleaner.
+ * All cleaning actions registered to a cleaner should be mutually compatible.
+ * @since 9
+ */
+public final class Cleaner {
+
+ /**
+ * The Cleaner implementation.
+ */
+ final CleanerImpl impl;
+
+ static {
+ CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl);
+ }
+
+ /**
+ * Construct a Cleaner implementation and start it.
+ */
+ private Cleaner() {
+ impl = new CleanerImpl();
+ }
+
+ /**
+ * Returns a new {@code Cleaner}.
+ * <p>
+ * The cleaner creates a {@link Thread#setDaemon(boolean) daemon thread}
+ * to process the phantom reachable objects and to invoke cleaning actions.
+ * The {@linkplain java.lang.Thread#getContextClassLoader context class loader}
+ * of the thread is set to the
+ * {@link ClassLoader#getSystemClassLoader() system class loader}.
+ * The thread has no permissions, enforced only if a
+ * {@link java.lang.System#setSecurityManager(SecurityManager) SecurityManager is set}.
+ * <p>
+ * The cleaner terminates when it is phantom reachable and all of the
+ * registered cleaning actions are complete.
+ *
+ * @return a new {@code Cleaner}
+ *
+ * @throws SecurityException if the current thread is not allowed to
+ * create or start the thread.
+ */
+ public static Cleaner create() {
+ Cleaner cleaner = new Cleaner();
+ cleaner.impl.start(cleaner, null);
+ return cleaner;
+ }
+
+ /**
+ * Returns a new {@code Cleaner} using a {@code Thread} from the {@code ThreadFactory}.
+ * <p>
+ * A thread from the thread factory's {@link ThreadFactory#newThread(Runnable) newThread}
+ * method is set to be a {@link Thread#setDaemon(boolean) daemon thread}
+ * and started to process phantom reachable objects and invoke cleaning actions.
+ * On each call the {@link ThreadFactory#newThread(Runnable) thread factory}
+ * must provide a Thread that is suitable for performing the cleaning actions.
+ * <p>
+ * The cleaner terminates when it is phantom reachable and all of the
+ * registered cleaning actions are complete.
+ *
+ * @param threadFactory a {@code ThreadFactory} to return a new {@code Thread}
+ * to process cleaning actions
+ * @return a new {@code Cleaner}
+ *
+ * @throws IllegalThreadStateException if the thread from the thread
+ * factory was {@link Thread.State#NEW not a new thread}.
+ * @throws SecurityException if the current thread is not allowed to
+ * create or start the thread.
+ */
+ public static Cleaner create(ThreadFactory threadFactory) {
+ Objects.requireNonNull(threadFactory, "threadFactory");
+ Cleaner cleaner = new Cleaner();
+ cleaner.impl.start(cleaner, threadFactory);
+ return cleaner;
+ }
+
+ /**
+ * Registers an object and a cleaning action to run when the object
+ * becomes phantom reachable.
+ * Refer to the <a href="#compatible-cleaners">API Note</a> above for
+ * cautions about the behavior of cleaning actions.
+ *
+ * @param obj the object to monitor
+ * @param action a {@code Runnable} to invoke when the object becomes phantom reachable
+ * @return a {@code Cleanable} instance
+ */
+ public Cleanable register(Object obj, Runnable action) {
+ Objects.requireNonNull(obj, "obj");
+ Objects.requireNonNull(action, "action");
+ return new CleanerImpl.PhantomCleanableRef(obj, this, action);
+ }
+
+ /**
+ * {@code Cleanable} represents an object and a
+ * cleaning action registered in a {@code Cleaner}.
+ * @since 9
+ */
+ public interface Cleanable {
+ /**
+ * Unregisters the cleanable and invokes the cleaning action.
+ * The cleanable's cleaning action is invoked at most once
+ * regardless of the number of calls to {@code clean}.
+ */
+ void clean();
+ }
+
+}
--- a/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Finalizer.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,6 @@
import java.security.AccessController;
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
import sun.misc.VM;
final class Finalizer extends FinalReference<Object> { /* Package-private; must be in
@@ -131,7 +130,7 @@
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
- Thread sft = new ManagedLocalsThread(tg, proc, "Secondary finalizer");
+ Thread sft = new Thread(tg, proc, "Secondary finalizer", 0, false);
sft.start();
try {
sft.join();
@@ -190,10 +189,10 @@
}}});
}
- private static class FinalizerThread extends ManagedLocalsThread {
+ private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) {
- super(g, "Finalizer");
+ super(g, null, "Finalizer", 0, false);
}
public void run() {
// in case of recursive call to run()
--- a/jdk/src/java.base/share/classes/java/lang/ref/Reference.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/ref/Reference.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,6 @@
import jdk.internal.HotSpotIntrinsicCandidate;
import jdk.internal.misc.JavaLangRefAccess;
import jdk.internal.misc.SharedSecrets;
-import sun.misc.ManagedLocalsThread;
/**
* Abstract base class for reference objects. This class defines the
@@ -128,7 +127,7 @@
/* High-priority thread to enqueue pending References
*/
- private static class ReferenceHandler extends ManagedLocalsThread {
+ private static class ReferenceHandler extends Thread {
private static void ensureClassInitialized(Class<?> clazz) {
try {
@@ -147,7 +146,7 @@
}
ReferenceHandler(ThreadGroup g, String name) {
- super(g, name);
+ super(g, null, name, 0, false);
}
public void run() {
--- a/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/ref/ReferenceQueue.java Wed Jan 06 14:54:24 2016 +0000
@@ -53,7 +53,7 @@
private static class Lock { };
private Lock lock = new Lock();
- private volatile Reference<? extends T> head = null;
+ private volatile Reference<? extends T> head;
private long queueLength = 0;
boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
--- a/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/ref/package-info.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -45,6 +45,8 @@
* (or values) from being reclaimed, and phantom references are for
* scheduling pre-mortem cleanup actions in a more flexible way than
* is possible with the Java finalization mechanism.
+ * Post-mortem cleanup actions can be registered and managed by a
+ * {@link java.lang.ref.Cleaner}.
*
* <p> Each reference-object type is implemented by a subclass of the
* abstract base {@link java.lang.ref.Reference} class.
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedArrayType.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,4 +42,19 @@
* @see GenericArrayType#getGenericComponentType()
*/
AnnotatedType getAnnotatedGenericComponentType();
+
+ /**
+ * Returns the potentially annotated type that this type is a member of, if
+ * this type represents a nested type. For example, if this type is
+ * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+ *
+ * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+ * of {@code AnnotatedArrayType}.
+ *
+ * @return {@code null}
+ *
+ * @since 1.9
+ */
+ @Override
+ AnnotatedType getAnnotatedOwnerType();
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedParameterizedType.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,4 +41,26 @@
* @see ParameterizedType#getActualTypeArguments()
*/
AnnotatedType[] getAnnotatedActualTypeArguments();
+
+ /**
+ * Returns the potentially annotated type that this type is a member of, if
+ * this type represents a nested type. For example, if this type is
+ * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+ *
+ * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+ * top-level type, or a local or anonymous class, or a primitive type, or
+ * void.
+ *
+ * @return an {@code AnnotatedType} object representing the potentially
+ * annotated type that this type is a member of, or {@code null}
+ * @throws TypeNotPresentException if the owner type
+ * refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if the owner type
+ * refers to a parameterized type that cannot be instantiated
+ * for any reason
+ *
+ * @since 1.9
+ */
+ @Override
+ AnnotatedType getAnnotatedOwnerType();
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedType.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,6 +36,37 @@
public interface AnnotatedType extends AnnotatedElement {
/**
+ * Returns the potentially annotated type that this type is a member of, if
+ * this type represents a nested type. For example, if this type is
+ * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+ *
+ * <p>Returns {@code null} if this {@code AnnotatedType} represents a
+ * top-level type, or a local or anonymous class, or a primitive type, or
+ * void.
+ *
+ * <p>Returns {@code null} if this {@code AnnotatedType} is an instance of
+ * {@code AnnotatedArrayType}, {@code AnnotatedTypeVariable}, or
+ * {@code AnnotatedWildcardType}.
+ *
+ * @implSpec
+ * This default implementation returns {@code null} and performs no other
+ * action.
+ *
+ * @return an {@code AnnotatedType} object representing the potentially
+ * annotated type that this type is a member of, or {@code null}
+ * @throws TypeNotPresentException if the owner type
+ * refers to a non-existent type declaration
+ * @throws MalformedParameterizedTypeException if the owner type
+ * refers to a parameterized type that cannot be instantiated
+ * for any reason
+ *
+ * @since 1.9
+ */
+ default AnnotatedType getAnnotatedOwnerType() {
+ return null;
+ }
+
+ /**
* Returns the underlying type that this annotated type represents.
*
* @return the type this annotated type represents
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedTypeVariable.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,4 +43,19 @@
* @see TypeVariable#getBounds()
*/
AnnotatedType[] getAnnotatedBounds();
+
+ /**
+ * Returns the potentially annotated type that this type is a member of, if
+ * this type represents a nested type. For example, if this type is
+ * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+ *
+ * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+ * of {@code AnnotatedTypeVariable}.
+ *
+ * @return {@code null}
+ *
+ * @since 1.9
+ */
+ @Override
+ AnnotatedType getAnnotatedOwnerType();
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/AnnotatedWildcardType.java Wed Jan 06 14:54:24 2016 +0000
@@ -54,4 +54,19 @@
* @see WildcardType#getUpperBounds()
*/
AnnotatedType[] getAnnotatedUpperBounds();
+
+ /**
+ * Returns the potentially annotated type that this type is a member of, if
+ * this type represents a nested type. For example, if this type is
+ * {@code @TA O<T>.I<S>}, return a representation of {@code @TA O<T>}.
+ *
+ * <p>Returns {@code null} for an {@code AnnotatedType} that is an instance
+ * of {@code AnnotatedWildcardType}.
+ *
+ * @return {@code null}
+ *
+ * @since 1.9
+ */
+ @Override
+ AnnotatedType getAnnotatedOwnerType();
}
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java Wed Jan 06 14:54:24 2016 +0000
@@ -205,7 +205,7 @@
return tmp;
}
- private transient volatile Type parameterTypeCache = null;
+ private transient volatile Type parameterTypeCache;
/**
* Returns a {@code Class} object that identifies the
@@ -237,7 +237,7 @@
return executable.getAnnotatedParameterTypes()[index];
}
- private transient volatile Class<?> parameterClassCache = null;
+ private transient volatile Class<?> parameterClassCache;
/**
* Returns {@code true} if this parameter is implicitly declared
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed Jan 06 14:54:24 2016 +0000
@@ -34,7 +34,6 @@
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
-import sun.misc.ProxyGenerator;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,2031 @@
+/*
+ * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.lang.reflect;
+
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import sun.security.action.GetBooleanAction;
+
+/**
+ * ProxyGenerator contains the code to generate a dynamic proxy class
+ * for the java.lang.reflect.Proxy API.
+ *
+ * The external interfaces to ProxyGenerator is the static
+ * "generateProxyClass" method.
+ *
+ * @author Peter Jones
+ * @since 1.3
+ */
+class ProxyGenerator {
+ /*
+ * In the comments below, "JVMS" refers to The Java Virtual Machine
+ * Specification Second Edition and "JLS" refers to the original
+ * version of The Java Language Specification, unless otherwise
+ * specified.
+ */
+
+ /* generate 1.5-era class file version */
+ private static final int CLASSFILE_MAJOR_VERSION = 49;
+ private static final int CLASSFILE_MINOR_VERSION = 0;
+
+ /*
+ * beginning of constants copied from
+ * sun.tools.java.RuntimeConstants (which no longer exists):
+ */
+
+ /* constant pool tags */
+ private static final int CONSTANT_UTF8 = 1;
+ private static final int CONSTANT_UNICODE = 2;
+ private static final int CONSTANT_INTEGER = 3;
+ private static final int CONSTANT_FLOAT = 4;
+ private static final int CONSTANT_LONG = 5;
+ private static final int CONSTANT_DOUBLE = 6;
+ private static final int CONSTANT_CLASS = 7;
+ private static final int CONSTANT_STRING = 8;
+ private static final int CONSTANT_FIELD = 9;
+ private static final int CONSTANT_METHOD = 10;
+ private static final int CONSTANT_INTERFACEMETHOD = 11;
+ private static final int CONSTANT_NAMEANDTYPE = 12;
+
+ /* access and modifier flags */
+ private static final int ACC_PUBLIC = 0x00000001;
+ private static final int ACC_PRIVATE = 0x00000002;
+// private static final int ACC_PROTECTED = 0x00000004;
+ private static final int ACC_STATIC = 0x00000008;
+ private static final int ACC_FINAL = 0x00000010;
+// private static final int ACC_SYNCHRONIZED = 0x00000020;
+// private static final int ACC_VOLATILE = 0x00000040;
+// private static final int ACC_TRANSIENT = 0x00000080;
+// private static final int ACC_NATIVE = 0x00000100;
+// private static final int ACC_INTERFACE = 0x00000200;
+// private static final int ACC_ABSTRACT = 0x00000400;
+ private static final int ACC_SUPER = 0x00000020;
+// private static final int ACC_STRICT = 0x00000800;
+
+ /* opcodes */
+// private static final int opc_nop = 0;
+ private static final int opc_aconst_null = 1;
+// private static final int opc_iconst_m1 = 2;
+ private static final int opc_iconst_0 = 3;
+// private static final int opc_iconst_1 = 4;
+// private static final int opc_iconst_2 = 5;
+// private static final int opc_iconst_3 = 6;
+// private static final int opc_iconst_4 = 7;
+// private static final int opc_iconst_5 = 8;
+// private static final int opc_lconst_0 = 9;
+// private static final int opc_lconst_1 = 10;
+// private static final int opc_fconst_0 = 11;
+// private static final int opc_fconst_1 = 12;
+// private static final int opc_fconst_2 = 13;
+// private static final int opc_dconst_0 = 14;
+// private static final int opc_dconst_1 = 15;
+ private static final int opc_bipush = 16;
+ private static final int opc_sipush = 17;
+ private static final int opc_ldc = 18;
+ private static final int opc_ldc_w = 19;
+// private static final int opc_ldc2_w = 20;
+ private static final int opc_iload = 21;
+ private static final int opc_lload = 22;
+ private static final int opc_fload = 23;
+ private static final int opc_dload = 24;
+ private static final int opc_aload = 25;
+ private static final int opc_iload_0 = 26;
+// private static final int opc_iload_1 = 27;
+// private static final int opc_iload_2 = 28;
+// private static final int opc_iload_3 = 29;
+ private static final int opc_lload_0 = 30;
+// private static final int opc_lload_1 = 31;
+// private static final int opc_lload_2 = 32;
+// private static final int opc_lload_3 = 33;
+ private static final int opc_fload_0 = 34;
+// private static final int opc_fload_1 = 35;
+// private static final int opc_fload_2 = 36;
+// private static final int opc_fload_3 = 37;
+ private static final int opc_dload_0 = 38;
+// private static final int opc_dload_1 = 39;
+// private static final int opc_dload_2 = 40;
+// private static final int opc_dload_3 = 41;
+ private static final int opc_aload_0 = 42;
+// private static final int opc_aload_1 = 43;
+// private static final int opc_aload_2 = 44;
+// private static final int opc_aload_3 = 45;
+// private static final int opc_iaload = 46;
+// private static final int opc_laload = 47;
+// private static final int opc_faload = 48;
+// private static final int opc_daload = 49;
+// private static final int opc_aaload = 50;
+// private static final int opc_baload = 51;
+// private static final int opc_caload = 52;
+// private static final int opc_saload = 53;
+// private static final int opc_istore = 54;
+// private static final int opc_lstore = 55;
+// private static final int opc_fstore = 56;
+// private static final int opc_dstore = 57;
+ private static final int opc_astore = 58;
+// private static final int opc_istore_0 = 59;
+// private static final int opc_istore_1 = 60;
+// private static final int opc_istore_2 = 61;
+// private static final int opc_istore_3 = 62;
+// private static final int opc_lstore_0 = 63;
+// private static final int opc_lstore_1 = 64;
+// private static final int opc_lstore_2 = 65;
+// private static final int opc_lstore_3 = 66;
+// private static final int opc_fstore_0 = 67;
+// private static final int opc_fstore_1 = 68;
+// private static final int opc_fstore_2 = 69;
+// private static final int opc_fstore_3 = 70;
+// private static final int opc_dstore_0 = 71;
+// private static final int opc_dstore_1 = 72;
+// private static final int opc_dstore_2 = 73;
+// private static final int opc_dstore_3 = 74;
+ private static final int opc_astore_0 = 75;
+// private static final int opc_astore_1 = 76;
+// private static final int opc_astore_2 = 77;
+// private static final int opc_astore_3 = 78;
+// private static final int opc_iastore = 79;
+// private static final int opc_lastore = 80;
+// private static final int opc_fastore = 81;
+// private static final int opc_dastore = 82;
+ private static final int opc_aastore = 83;
+// private static final int opc_bastore = 84;
+// private static final int opc_castore = 85;
+// private static final int opc_sastore = 86;
+ private static final int opc_pop = 87;
+// private static final int opc_pop2 = 88;
+ private static final int opc_dup = 89;
+// private static final int opc_dup_x1 = 90;
+// private static final int opc_dup_x2 = 91;
+// private static final int opc_dup2 = 92;
+// private static final int opc_dup2_x1 = 93;
+// private static final int opc_dup2_x2 = 94;
+// private static final int opc_swap = 95;
+// private static final int opc_iadd = 96;
+// private static final int opc_ladd = 97;
+// private static final int opc_fadd = 98;
+// private static final int opc_dadd = 99;
+// private static final int opc_isub = 100;
+// private static final int opc_lsub = 101;
+// private static final int opc_fsub = 102;
+// private static final int opc_dsub = 103;
+// private static final int opc_imul = 104;
+// private static final int opc_lmul = 105;
+// private static final int opc_fmul = 106;
+// private static final int opc_dmul = 107;
+// private static final int opc_idiv = 108;
+// private static final int opc_ldiv = 109;
+// private static final int opc_fdiv = 110;
+// private static final int opc_ddiv = 111;
+// private static final int opc_irem = 112;
+// private static final int opc_lrem = 113;
+// private static final int opc_frem = 114;
+// private static final int opc_drem = 115;
+// private static final int opc_ineg = 116;
+// private static final int opc_lneg = 117;
+// private static final int opc_fneg = 118;
+// private static final int opc_dneg = 119;
+// private static final int opc_ishl = 120;
+// private static final int opc_lshl = 121;
+// private static final int opc_ishr = 122;
+// private static final int opc_lshr = 123;
+// private static final int opc_iushr = 124;
+// private static final int opc_lushr = 125;
+// private static final int opc_iand = 126;
+// private static final int opc_land = 127;
+// private static final int opc_ior = 128;
+// private static final int opc_lor = 129;
+// private static final int opc_ixor = 130;
+// private static final int opc_lxor = 131;
+// private static final int opc_iinc = 132;
+// private static final int opc_i2l = 133;
+// private static final int opc_i2f = 134;
+// private static final int opc_i2d = 135;
+// private static final int opc_l2i = 136;
+// private static final int opc_l2f = 137;
+// private static final int opc_l2d = 138;
+// private static final int opc_f2i = 139;
+// private static final int opc_f2l = 140;
+// private static final int opc_f2d = 141;
+// private static final int opc_d2i = 142;
+// private static final int opc_d2l = 143;
+// private static final int opc_d2f = 144;
+// private static final int opc_i2b = 145;
+// private static final int opc_i2c = 146;
+// private static final int opc_i2s = 147;
+// private static final int opc_lcmp = 148;
+// private static final int opc_fcmpl = 149;
+// private static final int opc_fcmpg = 150;
+// private static final int opc_dcmpl = 151;
+// private static final int opc_dcmpg = 152;
+// private static final int opc_ifeq = 153;
+// private static final int opc_ifne = 154;
+// private static final int opc_iflt = 155;
+// private static final int opc_ifge = 156;
+// private static final int opc_ifgt = 157;
+// private static final int opc_ifle = 158;
+// private static final int opc_if_icmpeq = 159;
+// private static final int opc_if_icmpne = 160;
+// private static final int opc_if_icmplt = 161;
+// private static final int opc_if_icmpge = 162;
+// private static final int opc_if_icmpgt = 163;
+// private static final int opc_if_icmple = 164;
+// private static final int opc_if_acmpeq = 165;
+// private static final int opc_if_acmpne = 166;
+// private static final int opc_goto = 167;
+// private static final int opc_jsr = 168;
+// private static final int opc_ret = 169;
+// private static final int opc_tableswitch = 170;
+// private static final int opc_lookupswitch = 171;
+ private static final int opc_ireturn = 172;
+ private static final int opc_lreturn = 173;
+ private static final int opc_freturn = 174;
+ private static final int opc_dreturn = 175;
+ private static final int opc_areturn = 176;
+ private static final int opc_return = 177;
+ private static final int opc_getstatic = 178;
+ private static final int opc_putstatic = 179;
+ private static final int opc_getfield = 180;
+// private static final int opc_putfield = 181;
+ private static final int opc_invokevirtual = 182;
+ private static final int opc_invokespecial = 183;
+ private static final int opc_invokestatic = 184;
+ private static final int opc_invokeinterface = 185;
+ private static final int opc_new = 187;
+// private static final int opc_newarray = 188;
+ private static final int opc_anewarray = 189;
+// private static final int opc_arraylength = 190;
+ private static final int opc_athrow = 191;
+ private static final int opc_checkcast = 192;
+// private static final int opc_instanceof = 193;
+// private static final int opc_monitorenter = 194;
+// private static final int opc_monitorexit = 195;
+ private static final int opc_wide = 196;
+// private static final int opc_multianewarray = 197;
+// private static final int opc_ifnull = 198;
+// private static final int opc_ifnonnull = 199;
+// private static final int opc_goto_w = 200;
+// private static final int opc_jsr_w = 201;
+
+ // end of constants copied from sun.tools.java.RuntimeConstants
+
+ /** name of the superclass of proxy classes */
+ private static final String superclassName = "java/lang/reflect/Proxy";
+
+ /** name of field for storing a proxy instance's invocation handler */
+ private static final String handlerFieldName = "h";
+
+ /** debugging flag for saving generated class files */
+ private static final boolean saveGeneratedFiles =
+ java.security.AccessController.doPrivileged(
+ new GetBooleanAction(
+ "jdk.proxy.ProxyGenerator.saveGeneratedFiles")).booleanValue();
+
+ /**
+ * Generate a public proxy class given a name and a list of proxy interfaces.
+ */
+ static byte[] generateProxyClass(final String name,
+ Class<?>[] interfaces) {
+ return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
+ }
+
+ /**
+ * Generate a proxy class given a name and a list of proxy interfaces.
+ *
+ * @param name the class name of the proxy class
+ * @param interfaces proxy interfaces
+ * @param accessFlags access flags of the proxy class
+ */
+ static byte[] generateProxyClass(final String name,
+ Class<?>[] interfaces,
+ int accessFlags)
+ {
+ ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
+ final byte[] classFile = gen.generateClassFile();
+
+ if (saveGeneratedFiles) {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ try {
+ int i = name.lastIndexOf('.');
+ Path path;
+ if (i > 0) {
+ Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+ Files.createDirectories(dir);
+ path = dir.resolve(name.substring(i+1, name.length()) + ".class");
+ } else {
+ path = Paths.get(name + ".class");
+ }
+ Files.write(path, classFile);
+ return null;
+ } catch (IOException e) {
+ throw new InternalError(
+ "I/O exception saving generated file: " + e);
+ }
+ }
+ });
+ }
+
+ return classFile;
+ }
+
+ /* preloaded Method objects for methods in java.lang.Object */
+ private static Method hashCodeMethod;
+ private static Method equalsMethod;
+ private static Method toStringMethod;
+ static {
+ try {
+ hashCodeMethod = Object.class.getMethod("hashCode");
+ equalsMethod =
+ Object.class.getMethod("equals", new Class<?>[] { Object.class });
+ toStringMethod = Object.class.getMethod("toString");
+ } catch (NoSuchMethodException e) {
+ throw new NoSuchMethodError(e.getMessage());
+ }
+ }
+
+ /** name of proxy class */
+ private String className;
+
+ /** proxy interfaces */
+ private Class<?>[] interfaces;
+
+ /** proxy class access flags */
+ private int accessFlags;
+
+ /** constant pool of class being generated */
+ private ConstantPool cp = new ConstantPool();
+
+ /** FieldInfo struct for each field of generated class */
+ private List<FieldInfo> fields = new ArrayList<>();
+
+ /** MethodInfo struct for each method of generated class */
+ private List<MethodInfo> methods = new ArrayList<>();
+
+ /**
+ * maps method signature string to list of ProxyMethod objects for
+ * proxy methods with that signature
+ */
+ private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
+
+ /** count of ProxyMethod objects added to proxyMethods */
+ private int proxyMethodCount = 0;
+
+ /**
+ * Construct a ProxyGenerator to generate a proxy class with the
+ * specified name and for the given interfaces.
+ *
+ * A ProxyGenerator object contains the state for the ongoing
+ * generation of a particular proxy class.
+ */
+ private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
+ this.className = className;
+ this.interfaces = interfaces;
+ this.accessFlags = accessFlags;
+ }
+
+ /**
+ * Generate a class file for the proxy class. This method drives the
+ * class file generation process.
+ */
+ private byte[] generateClassFile() {
+
+ /* ============================================================
+ * Step 1: Assemble ProxyMethod objects for all methods to
+ * generate proxy dispatching code for.
+ */
+
+ /*
+ * Record that proxy methods are needed for the hashCode, equals,
+ * and toString methods of java.lang.Object. This is done before
+ * the methods from the proxy interfaces so that the methods from
+ * java.lang.Object take precedence over duplicate methods in the
+ * proxy interfaces.
+ */
+ addProxyMethod(hashCodeMethod, Object.class);
+ addProxyMethod(equalsMethod, Object.class);
+ addProxyMethod(toStringMethod, Object.class);
+
+ /*
+ * Now record all of the methods from the proxy interfaces, giving
+ * earlier interfaces precedence over later ones with duplicate
+ * methods.
+ */
+ for (Class<?> intf : interfaces) {
+ for (Method m : intf.getMethods()) {
+ addProxyMethod(m, intf);
+ }
+ }
+
+ /*
+ * For each set of proxy methods with the same signature,
+ * verify that the methods' return types are compatible.
+ */
+ for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+ checkReturnTypes(sigmethods);
+ }
+
+ /* ============================================================
+ * Step 2: Assemble FieldInfo and MethodInfo structs for all of
+ * fields and methods in the class we are generating.
+ */
+ try {
+ methods.add(generateConstructor());
+
+ for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+ for (ProxyMethod pm : sigmethods) {
+
+ // add static field for method's Method object
+ fields.add(new FieldInfo(pm.methodFieldName,
+ "Ljava/lang/reflect/Method;",
+ ACC_PRIVATE | ACC_STATIC));
+
+ // generate code for proxy method and add it
+ methods.add(pm.generateMethod());
+ }
+ }
+
+ methods.add(generateStaticInitializer());
+
+ } catch (IOException e) {
+ throw new InternalError("unexpected I/O Exception", e);
+ }
+
+ if (methods.size() > 65535) {
+ throw new IllegalArgumentException("method limit exceeded");
+ }
+ if (fields.size() > 65535) {
+ throw new IllegalArgumentException("field limit exceeded");
+ }
+
+ /* ============================================================
+ * Step 3: Write the final class file.
+ */
+
+ /*
+ * Make sure that constant pool indexes are reserved for the
+ * following items before starting to write the final class file.
+ */
+ cp.getClass(dotToSlash(className));
+ cp.getClass(superclassName);
+ for (Class<?> intf: interfaces) {
+ cp.getClass(dotToSlash(intf.getName()));
+ }
+
+ /*
+ * Disallow new constant pool additions beyond this point, since
+ * we are about to write the final constant pool table.
+ */
+ cp.setReadOnly();
+
+ ByteArrayOutputStream bout = new ByteArrayOutputStream();
+ DataOutputStream dout = new DataOutputStream(bout);
+
+ try {
+ /*
+ * Write all the items of the "ClassFile" structure.
+ * See JVMS section 4.1.
+ */
+ // u4 magic;
+ dout.writeInt(0xCAFEBABE);
+ // u2 minor_version;
+ dout.writeShort(CLASSFILE_MINOR_VERSION);
+ // u2 major_version;
+ dout.writeShort(CLASSFILE_MAJOR_VERSION);
+
+ cp.write(dout); // (write constant pool)
+
+ // u2 access_flags;
+ dout.writeShort(accessFlags);
+ // u2 this_class;
+ dout.writeShort(cp.getClass(dotToSlash(className)));
+ // u2 super_class;
+ dout.writeShort(cp.getClass(superclassName));
+
+ // u2 interfaces_count;
+ dout.writeShort(interfaces.length);
+ // u2 interfaces[interfaces_count];
+ for (Class<?> intf : interfaces) {
+ dout.writeShort(cp.getClass(
+ dotToSlash(intf.getName())));
+ }
+
+ // u2 fields_count;
+ dout.writeShort(fields.size());
+ // field_info fields[fields_count];
+ for (FieldInfo f : fields) {
+ f.write(dout);
+ }
+
+ // u2 methods_count;
+ dout.writeShort(methods.size());
+ // method_info methods[methods_count];
+ for (MethodInfo m : methods) {
+ m.write(dout);
+ }
+
+ // u2 attributes_count;
+ dout.writeShort(0); // (no ClassFile attributes for proxy classes)
+
+ } catch (IOException e) {
+ throw new InternalError("unexpected I/O Exception", e);
+ }
+
+ return bout.toByteArray();
+ }
+
+ /**
+ * Add another method to be proxied, either by creating a new
+ * ProxyMethod object or augmenting an old one for a duplicate
+ * method.
+ *
+ * "fromClass" indicates the proxy interface that the method was
+ * found through, which may be different from (a subinterface of)
+ * the method's "declaring class". Note that the first Method
+ * object passed for a given name and descriptor identifies the
+ * Method object (and thus the declaring class) that will be
+ * passed to the invocation handler's "invoke" method for a given
+ * set of duplicate methods.
+ */
+ private void addProxyMethod(Method m, Class<?> fromClass) {
+ String name = m.getName();
+ Class<?>[] parameterTypes = m.getParameterTypes();
+ Class<?> returnType = m.getReturnType();
+ Class<?>[] exceptionTypes = m.getExceptionTypes();
+
+ String sig = name + getParameterDescriptors(parameterTypes);
+ List<ProxyMethod> sigmethods = proxyMethods.get(sig);
+ if (sigmethods != null) {
+ for (ProxyMethod pm : sigmethods) {
+ if (returnType == pm.returnType) {
+ /*
+ * Found a match: reduce exception types to the
+ * greatest set of exceptions that can thrown
+ * compatibly with the throws clauses of both
+ * overridden methods.
+ */
+ List<Class<?>> legalExceptions = new ArrayList<>();
+ collectCompatibleTypes(
+ exceptionTypes, pm.exceptionTypes, legalExceptions);
+ collectCompatibleTypes(
+ pm.exceptionTypes, exceptionTypes, legalExceptions);
+ pm.exceptionTypes = new Class<?>[legalExceptions.size()];
+ pm.exceptionTypes =
+ legalExceptions.toArray(pm.exceptionTypes);
+ return;
+ }
+ }
+ } else {
+ sigmethods = new ArrayList<>(3);
+ proxyMethods.put(sig, sigmethods);
+ }
+ sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
+ exceptionTypes, fromClass));
+ }
+
+ /**
+ * For a given set of proxy methods with the same signature, check
+ * that their return types are compatible according to the Proxy
+ * specification.
+ *
+ * Specifically, if there is more than one such method, then all
+ * of the return types must be reference types, and there must be
+ * one return type that is assignable to each of the rest of them.
+ */
+ private static void checkReturnTypes(List<ProxyMethod> methods) {
+ /*
+ * If there is only one method with a given signature, there
+ * cannot be a conflict. This is the only case in which a
+ * primitive (or void) return type is allowed.
+ */
+ if (methods.size() < 2) {
+ return;
+ }
+
+ /*
+ * List of return types that are not yet known to be
+ * assignable from ("covered" by) any of the others.
+ */
+ LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
+
+ nextNewReturnType:
+ for (ProxyMethod pm : methods) {
+ Class<?> newReturnType = pm.returnType;
+ if (newReturnType.isPrimitive()) {
+ throw new IllegalArgumentException(
+ "methods with same signature " +
+ getFriendlyMethodSignature(pm.methodName,
+ pm.parameterTypes) +
+ " but incompatible return types: " +
+ newReturnType.getName() + " and others");
+ }
+ boolean added = false;
+
+ /*
+ * Compare the new return type to the existing uncovered
+ * return types.
+ */
+ ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
+ while (liter.hasNext()) {
+ Class<?> uncoveredReturnType = liter.next();
+
+ /*
+ * If an existing uncovered return type is assignable
+ * to this new one, then we can forget the new one.
+ */
+ if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
+ assert !added;
+ continue nextNewReturnType;
+ }
+
+ /*
+ * If the new return type is assignable to an existing
+ * uncovered one, then should replace the existing one
+ * with the new one (or just forget the existing one,
+ * if the new one has already be put in the list).
+ */
+ if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
+ // (we can assume that each return type is unique)
+ if (!added) {
+ liter.set(newReturnType);
+ added = true;
+ } else {
+ liter.remove();
+ }
+ }
+ }
+
+ /*
+ * If we got through the list of existing uncovered return
+ * types without an assignability relationship, then add
+ * the new return type to the list of uncovered ones.
+ */
+ if (!added) {
+ uncoveredReturnTypes.add(newReturnType);
+ }
+ }
+
+ /*
+ * We shouldn't end up with more than one return type that is
+ * not assignable from any of the others.
+ */
+ if (uncoveredReturnTypes.size() > 1) {
+ ProxyMethod pm = methods.get(0);
+ throw new IllegalArgumentException(
+ "methods with same signature " +
+ getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
+ " but incompatible return types: " + uncoveredReturnTypes);
+ }
+ }
+
+ /**
+ * A FieldInfo object contains information about a particular field
+ * in the class being generated. The class mirrors the data items of
+ * the "field_info" structure of the class file format (see JVMS 4.5).
+ */
+ private class FieldInfo {
+ public int accessFlags;
+ public String name;
+ public String descriptor;
+
+ public FieldInfo(String name, String descriptor, int accessFlags) {
+ this.name = name;
+ this.descriptor = descriptor;
+ this.accessFlags = accessFlags;
+
+ /*
+ * Make sure that constant pool indexes are reserved for the
+ * following items before starting to write the final class file.
+ */
+ cp.getUtf8(name);
+ cp.getUtf8(descriptor);
+ }
+
+ public void write(DataOutputStream out) throws IOException {
+ /*
+ * Write all the items of the "field_info" structure.
+ * See JVMS section 4.5.
+ */
+ // u2 access_flags;
+ out.writeShort(accessFlags);
+ // u2 name_index;
+ out.writeShort(cp.getUtf8(name));
+ // u2 descriptor_index;
+ out.writeShort(cp.getUtf8(descriptor));
+ // u2 attributes_count;
+ out.writeShort(0); // (no field_info attributes for proxy classes)
+ }
+ }
+
+ /**
+ * An ExceptionTableEntry object holds values for the data items of
+ * an entry in the "exception_table" item of the "Code" attribute of
+ * "method_info" structures (see JVMS 4.7.3).
+ */
+ private static class ExceptionTableEntry {
+ public short startPc;
+ public short endPc;
+ public short handlerPc;
+ public short catchType;
+
+ public ExceptionTableEntry(short startPc, short endPc,
+ short handlerPc, short catchType)
+ {
+ this.startPc = startPc;
+ this.endPc = endPc;
+ this.handlerPc = handlerPc;
+ this.catchType = catchType;
+ }
+ };
+
+ /**
+ * A MethodInfo object contains information about a particular method
+ * in the class being generated. This class mirrors the data items of
+ * the "method_info" structure of the class file format (see JVMS 4.6).
+ */
+ private class MethodInfo {
+ public int accessFlags;
+ public String name;
+ public String descriptor;
+ public short maxStack;
+ public short maxLocals;
+ public ByteArrayOutputStream code = new ByteArrayOutputStream();
+ public List<ExceptionTableEntry> exceptionTable =
+ new ArrayList<ExceptionTableEntry>();
+ public short[] declaredExceptions;
+
+ public MethodInfo(String name, String descriptor, int accessFlags) {
+ this.name = name;
+ this.descriptor = descriptor;
+ this.accessFlags = accessFlags;
+
+ /*
+ * Make sure that constant pool indexes are reserved for the
+ * following items before starting to write the final class file.
+ */
+ cp.getUtf8(name);
+ cp.getUtf8(descriptor);
+ cp.getUtf8("Code");
+ cp.getUtf8("Exceptions");
+ }
+
+ public void write(DataOutputStream out) throws IOException {
+ /*
+ * Write all the items of the "method_info" structure.
+ * See JVMS section 4.6.
+ */
+ // u2 access_flags;
+ out.writeShort(accessFlags);
+ // u2 name_index;
+ out.writeShort(cp.getUtf8(name));
+ // u2 descriptor_index;
+ out.writeShort(cp.getUtf8(descriptor));
+ // u2 attributes_count;
+ out.writeShort(2); // (two method_info attributes:)
+
+ // Write "Code" attribute. See JVMS section 4.7.3.
+
+ // u2 attribute_name_index;
+ out.writeShort(cp.getUtf8("Code"));
+ // u4 attribute_length;
+ out.writeInt(12 + code.size() + 8 * exceptionTable.size());
+ // u2 max_stack;
+ out.writeShort(maxStack);
+ // u2 max_locals;
+ out.writeShort(maxLocals);
+ // u2 code_length;
+ out.writeInt(code.size());
+ // u1 code[code_length];
+ code.writeTo(out);
+ // u2 exception_table_length;
+ out.writeShort(exceptionTable.size());
+ for (ExceptionTableEntry e : exceptionTable) {
+ // u2 start_pc;
+ out.writeShort(e.startPc);
+ // u2 end_pc;
+ out.writeShort(e.endPc);
+ // u2 handler_pc;
+ out.writeShort(e.handlerPc);
+ // u2 catch_type;
+ out.writeShort(e.catchType);
+ }
+ // u2 attributes_count;
+ out.writeShort(0);
+
+ // write "Exceptions" attribute. See JVMS section 4.7.4.
+
+ // u2 attribute_name_index;
+ out.writeShort(cp.getUtf8("Exceptions"));
+ // u4 attributes_length;
+ out.writeInt(2 + 2 * declaredExceptions.length);
+ // u2 number_of_exceptions;
+ out.writeShort(declaredExceptions.length);
+ // u2 exception_index_table[number_of_exceptions];
+ for (short value : declaredExceptions) {
+ out.writeShort(value);
+ }
+ }
+
+ }
+
+ /**
+ * A ProxyMethod object represents a proxy method in the proxy class
+ * being generated: a method whose implementation will encode and
+ * dispatch invocations to the proxy instance's invocation handler.
+ */
+ private class ProxyMethod {
+
+ public String methodName;
+ public Class<?>[] parameterTypes;
+ public Class<?> returnType;
+ public Class<?>[] exceptionTypes;
+ public Class<?> fromClass;
+ public String methodFieldName;
+
+ private ProxyMethod(String methodName, Class<?>[] parameterTypes,
+ Class<?> returnType, Class<?>[] exceptionTypes,
+ Class<?> fromClass)
+ {
+ this.methodName = methodName;
+ this.parameterTypes = parameterTypes;
+ this.returnType = returnType;
+ this.exceptionTypes = exceptionTypes;
+ this.fromClass = fromClass;
+ this.methodFieldName = "m" + proxyMethodCount++;
+ }
+
+ /**
+ * Return a MethodInfo object for this method, including generating
+ * the code and exception table entry.
+ */
+ private MethodInfo generateMethod() throws IOException {
+ String desc = getMethodDescriptor(parameterTypes, returnType);
+ MethodInfo minfo = new MethodInfo(methodName, desc,
+ ACC_PUBLIC | ACC_FINAL);
+
+ int[] parameterSlot = new int[parameterTypes.length];
+ int nextSlot = 1;
+ for (int i = 0; i < parameterSlot.length; i++) {
+ parameterSlot[i] = nextSlot;
+ nextSlot += getWordsPerType(parameterTypes[i]);
+ }
+ int localSlot0 = nextSlot;
+ short pc, tryBegin = 0, tryEnd;
+
+ DataOutputStream out = new DataOutputStream(minfo.code);
+
+ code_aload(0, out);
+
+ out.writeByte(opc_getfield);
+ out.writeShort(cp.getFieldRef(
+ superclassName,
+ handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
+
+ code_aload(0, out);
+
+ out.writeByte(opc_getstatic);
+ out.writeShort(cp.getFieldRef(
+ dotToSlash(className),
+ methodFieldName, "Ljava/lang/reflect/Method;"));
+
+ if (parameterTypes.length > 0) {
+
+ code_ipush(parameterTypes.length, out);
+
+ out.writeByte(opc_anewarray);
+ out.writeShort(cp.getClass("java/lang/Object"));
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+
+ out.writeByte(opc_dup);
+
+ code_ipush(i, out);
+
+ codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
+
+ out.writeByte(opc_aastore);
+ }
+ } else {
+
+ out.writeByte(opc_aconst_null);
+ }
+
+ out.writeByte(opc_invokeinterface);
+ out.writeShort(cp.getInterfaceMethodRef(
+ "java/lang/reflect/InvocationHandler",
+ "invoke",
+ "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
+ "[Ljava/lang/Object;)Ljava/lang/Object;"));
+ out.writeByte(4);
+ out.writeByte(0);
+
+ if (returnType == void.class) {
+
+ out.writeByte(opc_pop);
+
+ out.writeByte(opc_return);
+
+ } else {
+
+ codeUnwrapReturnValue(returnType, out);
+ }
+
+ tryEnd = pc = (short) minfo.code.size();
+
+ List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
+ if (catchList.size() > 0) {
+
+ for (Class<?> ex : catchList) {
+ minfo.exceptionTable.add(new ExceptionTableEntry(
+ tryBegin, tryEnd, pc,
+ cp.getClass(dotToSlash(ex.getName()))));
+ }
+
+ out.writeByte(opc_athrow);
+
+ pc = (short) minfo.code.size();
+
+ minfo.exceptionTable.add(new ExceptionTableEntry(
+ tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
+
+ code_astore(localSlot0, out);
+
+ out.writeByte(opc_new);
+ out.writeShort(cp.getClass(
+ "java/lang/reflect/UndeclaredThrowableException"));
+
+ out.writeByte(opc_dup);
+
+ code_aload(localSlot0, out);
+
+ out.writeByte(opc_invokespecial);
+
+ out.writeShort(cp.getMethodRef(
+ "java/lang/reflect/UndeclaredThrowableException",
+ "<init>", "(Ljava/lang/Throwable;)V"));
+
+ out.writeByte(opc_athrow);
+ }
+
+ if (minfo.code.size() > 65535) {
+ throw new IllegalArgumentException("code size limit exceeded");
+ }
+
+ minfo.maxStack = 10;
+ minfo.maxLocals = (short) (localSlot0 + 1);
+ minfo.declaredExceptions = new short[exceptionTypes.length];
+ for (int i = 0; i < exceptionTypes.length; i++) {
+ minfo.declaredExceptions[i] = cp.getClass(
+ dotToSlash(exceptionTypes[i].getName()));
+ }
+
+ return minfo;
+ }
+
+ /**
+ * Generate code for wrapping an argument of the given type
+ * whose value can be found at the specified local variable
+ * index, in order for it to be passed (as an Object) to the
+ * invocation handler's "invoke" method. The code is written
+ * to the supplied stream.
+ */
+ private void codeWrapArgument(Class<?> type, int slot,
+ DataOutputStream out)
+ throws IOException
+ {
+ if (type.isPrimitive()) {
+ PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+ if (type == int.class ||
+ type == boolean.class ||
+ type == byte.class ||
+ type == char.class ||
+ type == short.class)
+ {
+ code_iload(slot, out);
+ } else if (type == long.class) {
+ code_lload(slot, out);
+ } else if (type == float.class) {
+ code_fload(slot, out);
+ } else if (type == double.class) {
+ code_dload(slot, out);
+ } else {
+ throw new AssertionError();
+ }
+
+ out.writeByte(opc_invokestatic);
+ out.writeShort(cp.getMethodRef(
+ prim.wrapperClassName,
+ "valueOf", prim.wrapperValueOfDesc));
+
+ } else {
+
+ code_aload(slot, out);
+ }
+ }
+
+ /**
+ * Generate code for unwrapping a return value of the given
+ * type from the invocation handler's "invoke" method (as type
+ * Object) to its correct type. The code is written to the
+ * supplied stream.
+ */
+ private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out)
+ throws IOException
+ {
+ if (type.isPrimitive()) {
+ PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
+
+ out.writeByte(opc_checkcast);
+ out.writeShort(cp.getClass(prim.wrapperClassName));
+
+ out.writeByte(opc_invokevirtual);
+ out.writeShort(cp.getMethodRef(
+ prim.wrapperClassName,
+ prim.unwrapMethodName, prim.unwrapMethodDesc));
+
+ if (type == int.class ||
+ type == boolean.class ||
+ type == byte.class ||
+ type == char.class ||
+ type == short.class)
+ {
+ out.writeByte(opc_ireturn);
+ } else if (type == long.class) {
+ out.writeByte(opc_lreturn);
+ } else if (type == float.class) {
+ out.writeByte(opc_freturn);
+ } else if (type == double.class) {
+ out.writeByte(opc_dreturn);
+ } else {
+ throw new AssertionError();
+ }
+
+ } else {
+
+ out.writeByte(opc_checkcast);
+ out.writeShort(cp.getClass(dotToSlash(type.getName())));
+
+ out.writeByte(opc_areturn);
+ }
+ }
+
+ /**
+ * Generate code for initializing the static field that stores
+ * the Method object for this proxy method. The code is written
+ * to the supplied stream.
+ */
+ private void codeFieldInitialization(DataOutputStream out)
+ throws IOException
+ {
+ codeClassForName(fromClass, out);
+
+ code_ldc(cp.getString(methodName), out);
+
+ code_ipush(parameterTypes.length, out);
+
+ out.writeByte(opc_anewarray);
+ out.writeShort(cp.getClass("java/lang/Class"));
+
+ for (int i = 0; i < parameterTypes.length; i++) {
+
+ out.writeByte(opc_dup);
+
+ code_ipush(i, out);
+
+ if (parameterTypes[i].isPrimitive()) {
+ PrimitiveTypeInfo prim =
+ PrimitiveTypeInfo.get(parameterTypes[i]);
+
+ out.writeByte(opc_getstatic);
+ out.writeShort(cp.getFieldRef(
+ prim.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
+
+ } else {
+ codeClassForName(parameterTypes[i], out);
+ }
+
+ out.writeByte(opc_aastore);
+ }
+
+ out.writeByte(opc_invokevirtual);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/Class",
+ "getMethod",
+ "(Ljava/lang/String;[Ljava/lang/Class;)" +
+ "Ljava/lang/reflect/Method;"));
+
+ out.writeByte(opc_putstatic);
+ out.writeShort(cp.getFieldRef(
+ dotToSlash(className),
+ methodFieldName, "Ljava/lang/reflect/Method;"));
+ }
+ }
+
+ /**
+ * Generate the constructor method for the proxy class.
+ */
+ private MethodInfo generateConstructor() throws IOException {
+ MethodInfo minfo = new MethodInfo(
+ "<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
+ ACC_PUBLIC);
+
+ DataOutputStream out = new DataOutputStream(minfo.code);
+
+ code_aload(0, out);
+
+ code_aload(1, out);
+
+ out.writeByte(opc_invokespecial);
+ out.writeShort(cp.getMethodRef(
+ superclassName,
+ "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
+
+ out.writeByte(opc_return);
+
+ minfo.maxStack = 10;
+ minfo.maxLocals = 2;
+ minfo.declaredExceptions = new short[0];
+
+ return minfo;
+ }
+
+ /**
+ * Generate the static initializer method for the proxy class.
+ */
+ private MethodInfo generateStaticInitializer() throws IOException {
+ MethodInfo minfo = new MethodInfo(
+ "<clinit>", "()V", ACC_STATIC);
+
+ int localSlot0 = 1;
+ short pc, tryBegin = 0, tryEnd;
+
+ DataOutputStream out = new DataOutputStream(minfo.code);
+
+ for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
+ for (ProxyMethod pm : sigmethods) {
+ pm.codeFieldInitialization(out);
+ }
+ }
+
+ out.writeByte(opc_return);
+
+ tryEnd = pc = (short) minfo.code.size();
+
+ minfo.exceptionTable.add(new ExceptionTableEntry(
+ tryBegin, tryEnd, pc,
+ cp.getClass("java/lang/NoSuchMethodException")));
+
+ code_astore(localSlot0, out);
+
+ out.writeByte(opc_new);
+ out.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
+
+ out.writeByte(opc_dup);
+
+ code_aload(localSlot0, out);
+
+ out.writeByte(opc_invokevirtual);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+ out.writeByte(opc_invokespecial);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
+
+ out.writeByte(opc_athrow);
+
+ pc = (short) minfo.code.size();
+
+ minfo.exceptionTable.add(new ExceptionTableEntry(
+ tryBegin, tryEnd, pc,
+ cp.getClass("java/lang/ClassNotFoundException")));
+
+ code_astore(localSlot0, out);
+
+ out.writeByte(opc_new);
+ out.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
+
+ out.writeByte(opc_dup);
+
+ code_aload(localSlot0, out);
+
+ out.writeByte(opc_invokevirtual);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
+
+ out.writeByte(opc_invokespecial);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/NoClassDefFoundError",
+ "<init>", "(Ljava/lang/String;)V"));
+
+ out.writeByte(opc_athrow);
+
+ if (minfo.code.size() > 65535) {
+ throw new IllegalArgumentException("code size limit exceeded");
+ }
+
+ minfo.maxStack = 10;
+ minfo.maxLocals = (short) (localSlot0 + 1);
+ minfo.declaredExceptions = new short[0];
+
+ return minfo;
+ }
+
+
+ /*
+ * =============== Code Generation Utility Methods ===============
+ */
+
+ /*
+ * The following methods generate code for the load or store operation
+ * indicated by their name for the given local variable. The code is
+ * written to the supplied stream.
+ */
+
+ private void code_iload(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out);
+ }
+
+ private void code_lload(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out);
+ }
+
+ private void code_fload(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out);
+ }
+
+ private void code_dload(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out);
+ }
+
+ private void code_aload(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out);
+ }
+
+// private void code_istore(int lvar, DataOutputStream out)
+// throws IOException
+// {
+// codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
+// }
+
+// private void code_lstore(int lvar, DataOutputStream out)
+// throws IOException
+// {
+// codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
+// }
+
+// private void code_fstore(int lvar, DataOutputStream out)
+// throws IOException
+// {
+// codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
+// }
+
+// private void code_dstore(int lvar, DataOutputStream out)
+// throws IOException
+// {
+// codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
+// }
+
+ private void code_astore(int lvar, DataOutputStream out)
+ throws IOException
+ {
+ codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out);
+ }
+
+ /**
+ * Generate code for a load or store instruction for the given local
+ * variable. The code is written to the supplied stream.
+ *
+ * "opcode" indicates the opcode form of the desired load or store
+ * instruction that takes an explicit local variable index, and
+ * "opcode_0" indicates the corresponding form of the instruction
+ * with the implicit index 0.
+ */
+ private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
+ DataOutputStream out)
+ throws IOException
+ {
+ assert lvar >= 0 && lvar <= 0xFFFF;
+ if (lvar <= 3) {
+ out.writeByte(opcode_0 + lvar);
+ } else if (lvar <= 0xFF) {
+ out.writeByte(opcode);
+ out.writeByte(lvar & 0xFF);
+ } else {
+ /*
+ * Use the "wide" instruction modifier for local variable
+ * indexes that do not fit into an unsigned byte.
+ */
+ out.writeByte(opc_wide);
+ out.writeByte(opcode);
+ out.writeShort(lvar & 0xFFFF);
+ }
+ }
+
+ /**
+ * Generate code for an "ldc" instruction for the given constant pool
+ * index (the "ldc_w" instruction is used if the index does not fit
+ * into an unsigned byte). The code is written to the supplied stream.
+ */
+ private void code_ldc(int index, DataOutputStream out)
+ throws IOException
+ {
+ assert index >= 0 && index <= 0xFFFF;
+ if (index <= 0xFF) {
+ out.writeByte(opc_ldc);
+ out.writeByte(index & 0xFF);
+ } else {
+ out.writeByte(opc_ldc_w);
+ out.writeShort(index & 0xFFFF);
+ }
+ }
+
+ /**
+ * Generate code to push a constant integer value on to the operand
+ * stack, using the "iconst_<i>", "bipush", or "sipush" instructions
+ * depending on the size of the value. The code is written to the
+ * supplied stream.
+ */
+ private void code_ipush(int value, DataOutputStream out)
+ throws IOException
+ {
+ if (value >= -1 && value <= 5) {
+ out.writeByte(opc_iconst_0 + value);
+ } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+ out.writeByte(opc_bipush);
+ out.writeByte(value & 0xFF);
+ } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+ out.writeByte(opc_sipush);
+ out.writeShort(value & 0xFFFF);
+ } else {
+ throw new AssertionError();
+ }
+ }
+
+ /**
+ * Generate code to invoke the Class.forName with the name of the given
+ * class to get its Class object at runtime. The code is written to
+ * the supplied stream. Note that the code generated by this method
+ * may caused the checked ClassNotFoundException to be thrown.
+ */
+ private void codeClassForName(Class<?> cl, DataOutputStream out)
+ throws IOException
+ {
+ code_ldc(cp.getString(cl.getName()), out);
+
+ out.writeByte(opc_invokestatic);
+ out.writeShort(cp.getMethodRef(
+ "java/lang/Class",
+ "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
+ }
+
+
+ /*
+ * ==================== General Utility Methods ====================
+ */
+
+ /**
+ * Convert a fully qualified class name that uses '.' as the package
+ * separator, the external representation used by the Java language
+ * and APIs, to a fully qualified class name that uses '/' as the
+ * package separator, the representation used in the class file
+ * format (see JVMS section 4.2).
+ */
+ private static String dotToSlash(String name) {
+ return name.replace('.', '/');
+ }
+
+ /**
+ * Return the "method descriptor" string for a method with the given
+ * parameter types and return type. See JVMS section 4.3.3.
+ */
+ private static String getMethodDescriptor(Class<?>[] parameterTypes,
+ Class<?> returnType)
+ {
+ return getParameterDescriptors(parameterTypes) +
+ ((returnType == void.class) ? "V" : getFieldType(returnType));
+ }
+
+ /**
+ * Return the list of "parameter descriptor" strings enclosed in
+ * parentheses corresponding to the given parameter types (in other
+ * words, a method descriptor without a return descriptor). This
+ * string is useful for constructing string keys for methods without
+ * regard to their return type.
+ */
+ private static String getParameterDescriptors(Class<?>[] parameterTypes) {
+ StringBuilder desc = new StringBuilder("(");
+ for (int i = 0; i < parameterTypes.length; i++) {
+ desc.append(getFieldType(parameterTypes[i]));
+ }
+ desc.append(')');
+ return desc.toString();
+ }
+
+ /**
+ * Return the "field type" string for the given type, appropriate for
+ * a field descriptor, a parameter descriptor, or a return descriptor
+ * other than "void". See JVMS section 4.3.2.
+ */
+ private static String getFieldType(Class<?> type) {
+ if (type.isPrimitive()) {
+ return PrimitiveTypeInfo.get(type).baseTypeString;
+ } else if (type.isArray()) {
+ /*
+ * According to JLS 20.3.2, the getName() method on Class does
+ * return the VM type descriptor format for array classes (only);
+ * using that should be quicker than the otherwise obvious code:
+ *
+ * return "[" + getTypeDescriptor(type.getComponentType());
+ */
+ return type.getName().replace('.', '/');
+ } else {
+ return "L" + dotToSlash(type.getName()) + ";";
+ }
+ }
+
+ /**
+ * Returns a human-readable string representing the signature of a
+ * method with the given name and parameter types.
+ */
+ private static String getFriendlyMethodSignature(String name,
+ Class<?>[] parameterTypes)
+ {
+ StringBuilder sig = new StringBuilder(name);
+ sig.append('(');
+ for (int i = 0; i < parameterTypes.length; i++) {
+ if (i > 0) {
+ sig.append(',');
+ }
+ Class<?> parameterType = parameterTypes[i];
+ int dimensions = 0;
+ while (parameterType.isArray()) {
+ parameterType = parameterType.getComponentType();
+ dimensions++;
+ }
+ sig.append(parameterType.getName());
+ while (dimensions-- > 0) {
+ sig.append("[]");
+ }
+ }
+ sig.append(')');
+ return sig.toString();
+ }
+
+ /**
+ * Return the number of abstract "words", or consecutive local variable
+ * indexes, required to contain a value of the given type. See JVMS
+ * section 3.6.1.
+ *
+ * Note that the original version of the JVMS contained a definition of
+ * this abstract notion of a "word" in section 3.4, but that definition
+ * was removed for the second edition.
+ */
+ private static int getWordsPerType(Class<?> type) {
+ if (type == long.class || type == double.class) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Add to the given list all of the types in the "from" array that
+ * are not already contained in the list and are assignable to at
+ * least one of the types in the "with" array.
+ *
+ * This method is useful for computing the greatest common set of
+ * declared exceptions from duplicate methods inherited from
+ * different interfaces.
+ */
+ private static void collectCompatibleTypes(Class<?>[] from,
+ Class<?>[] with,
+ List<Class<?>> list)
+ {
+ for (Class<?> fc: from) {
+ if (!list.contains(fc)) {
+ for (Class<?> wc: with) {
+ if (wc.isAssignableFrom(fc)) {
+ list.add(fc);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Given the exceptions declared in the throws clause of a proxy method,
+ * compute the exceptions that need to be caught from the invocation
+ * handler's invoke method and rethrown intact in the method's
+ * implementation before catching other Throwables and wrapping them
+ * in UndeclaredThrowableExceptions.
+ *
+ * The exceptions to be caught are returned in a List object. Each
+ * exception in the returned list is guaranteed to not be a subclass of
+ * any of the other exceptions in the list, so the catch blocks for
+ * these exceptions may be generated in any order relative to each other.
+ *
+ * Error and RuntimeException are each always contained by the returned
+ * list (if none of their superclasses are contained), since those
+ * unchecked exceptions should always be rethrown intact, and thus their
+ * subclasses will never appear in the returned list.
+ *
+ * The returned List will be empty if java.lang.Throwable is in the
+ * given list of declared exceptions, indicating that no exceptions
+ * need to be caught.
+ */
+ private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
+ List<Class<?>> uniqueList = new ArrayList<>();
+ // unique exceptions to catch
+
+ uniqueList.add(Error.class); // always catch/rethrow these
+ uniqueList.add(RuntimeException.class);
+
+ nextException:
+ for (Class<?> ex: exceptions) {
+ if (ex.isAssignableFrom(Throwable.class)) {
+ /*
+ * If Throwable is declared to be thrown by the proxy method,
+ * then no catch blocks are necessary, because the invoke
+ * can, at most, throw Throwable anyway.
+ */
+ uniqueList.clear();
+ break;
+ } else if (!Throwable.class.isAssignableFrom(ex)) {
+ /*
+ * Ignore types that cannot be thrown by the invoke method.
+ */
+ continue;
+ }
+ /*
+ * Compare this exception against the current list of
+ * exceptions that need to be caught:
+ */
+ for (int j = 0; j < uniqueList.size();) {
+ Class<?> ex2 = uniqueList.get(j);
+ if (ex2.isAssignableFrom(ex)) {
+ /*
+ * if a superclass of this exception is already on
+ * the list to catch, then ignore this one and continue;
+ */
+ continue nextException;
+ } else if (ex.isAssignableFrom(ex2)) {
+ /*
+ * if a subclass of this exception is on the list
+ * to catch, then remove it;
+ */
+ uniqueList.remove(j);
+ } else {
+ j++; // else continue comparing.
+ }
+ }
+ // This exception is unique (so far): add it to the list to catch.
+ uniqueList.add(ex);
+ }
+ return uniqueList;
+ }
+
+ /**
+ * A PrimitiveTypeInfo object contains assorted information about
+ * a primitive type in its public fields. The struct for a particular
+ * primitive type can be obtained using the static "get" method.
+ */
+ private static class PrimitiveTypeInfo {
+
+ /** "base type" used in various descriptors (see JVMS section 4.3.2) */
+ public String baseTypeString;
+
+ /** name of corresponding wrapper class */
+ public String wrapperClassName;
+
+ /** method descriptor for wrapper class "valueOf" factory method */
+ public String wrapperValueOfDesc;
+
+ /** name of wrapper class method for retrieving primitive value */
+ public String unwrapMethodName;
+
+ /** descriptor of same method */
+ public String unwrapMethodDesc;
+
+ private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>();
+ static {
+ add(byte.class, Byte.class);
+ add(char.class, Character.class);
+ add(double.class, Double.class);
+ add(float.class, Float.class);
+ add(int.class, Integer.class);
+ add(long.class, Long.class);
+ add(short.class, Short.class);
+ add(boolean.class, Boolean.class);
+ }
+
+ private static void add(Class<?> primitiveClass, Class<?> wrapperClass) {
+ table.put(primitiveClass,
+ new PrimitiveTypeInfo(primitiveClass, wrapperClass));
+ }
+
+ private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) {
+ assert primitiveClass.isPrimitive();
+
+ baseTypeString =
+ Array.newInstance(primitiveClass, 0)
+ .getClass().getName().substring(1);
+ wrapperClassName = dotToSlash(wrapperClass.getName());
+ wrapperValueOfDesc =
+ "(" + baseTypeString + ")L" + wrapperClassName + ";";
+ unwrapMethodName = primitiveClass.getName() + "Value";
+ unwrapMethodDesc = "()" + baseTypeString;
+ }
+
+ public static PrimitiveTypeInfo get(Class<?> cl) {
+ return table.get(cl);
+ }
+ }
+
+
+ /**
+ * A ConstantPool object represents the constant pool of a class file
+ * being generated. This representation of a constant pool is designed
+ * specifically for use by ProxyGenerator; in particular, it assumes
+ * that constant pool entries will not need to be resorted (for example,
+ * by their type, as the Java compiler does), so that the final index
+ * value can be assigned and used when an entry is first created.
+ *
+ * Note that new entries cannot be created after the constant pool has
+ * been written to a class file. To prevent such logic errors, a
+ * ConstantPool instance can be marked "read only", so that further
+ * attempts to add new entries will fail with a runtime exception.
+ *
+ * See JVMS section 4.4 for more information about the constant pool
+ * of a class file.
+ */
+ private static class ConstantPool {
+
+ /**
+ * list of constant pool entries, in constant pool index order.
+ *
+ * This list is used when writing the constant pool to a stream
+ * and for assigning the next index value. Note that element 0
+ * of this list corresponds to constant pool index 1.
+ */
+ private List<Entry> pool = new ArrayList<>(32);
+
+ /**
+ * maps constant pool data of all types to constant pool indexes.
+ *
+ * This map is used to look up the index of an existing entry for
+ * values of all types.
+ */
+ private Map<Object,Short> map = new HashMap<>(16);
+
+ /** true if no new constant pool entries may be added */
+ private boolean readOnly = false;
+
+ /**
+ * Get or assign the index for a CONSTANT_Utf8 entry.
+ */
+ public short getUtf8(String s) {
+ if (s == null) {
+ throw new NullPointerException();
+ }
+ return getValue(s);
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_Integer entry.
+ */
+ public short getInteger(int i) {
+ return getValue(i);
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_Float entry.
+ */
+ public short getFloat(float f) {
+ return getValue(new Float(f));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_Class entry.
+ */
+ public short getClass(String name) {
+ short utf8Index = getUtf8(name);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_CLASS, utf8Index));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_String entry.
+ */
+ public short getString(String s) {
+ short utf8Index = getUtf8(s);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_STRING, utf8Index));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_FieldRef entry.
+ */
+ public short getFieldRef(String className,
+ String name, String descriptor)
+ {
+ short classIndex = getClass(className);
+ short nameAndTypeIndex = getNameAndType(name, descriptor);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_FIELD, classIndex, nameAndTypeIndex));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_MethodRef entry.
+ */
+ public short getMethodRef(String className,
+ String name, String descriptor)
+ {
+ short classIndex = getClass(className);
+ short nameAndTypeIndex = getNameAndType(name, descriptor);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_METHOD, classIndex, nameAndTypeIndex));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
+ */
+ public short getInterfaceMethodRef(String className, String name,
+ String descriptor)
+ {
+ short classIndex = getClass(className);
+ short nameAndTypeIndex = getNameAndType(name, descriptor);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
+ }
+
+ /**
+ * Get or assign the index for a CONSTANT_NameAndType entry.
+ */
+ public short getNameAndType(String name, String descriptor) {
+ short nameIndex = getUtf8(name);
+ short descriptorIndex = getUtf8(descriptor);
+ return getIndirect(new IndirectEntry(
+ CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
+ }
+
+ /**
+ * Set this ConstantPool instance to be "read only".
+ *
+ * After this method has been called, further requests to get
+ * an index for a non-existent entry will cause an InternalError
+ * to be thrown instead of creating of the entry.
+ */
+ public void setReadOnly() {
+ readOnly = true;
+ }
+
+ /**
+ * Write this constant pool to a stream as part of
+ * the class file format.
+ *
+ * This consists of writing the "constant_pool_count" and
+ * "constant_pool[]" items of the "ClassFile" structure, as
+ * described in JVMS section 4.1.
+ */
+ public void write(OutputStream out) throws IOException {
+ DataOutputStream dataOut = new DataOutputStream(out);
+
+ // constant_pool_count: number of entries plus one
+ dataOut.writeShort(pool.size() + 1);
+
+ for (Entry e : pool) {
+ e.write(dataOut);
+ }
+ }
+
+ /**
+ * Add a new constant pool entry and return its index.
+ */
+ private short addEntry(Entry entry) {
+ pool.add(entry);
+ /*
+ * Note that this way of determining the index of the
+ * added entry is wrong if this pool supports
+ * CONSTANT_Long or CONSTANT_Double entries.
+ */
+ if (pool.size() >= 65535) {
+ throw new IllegalArgumentException(
+ "constant pool size limit exceeded");
+ }
+ return (short) pool.size();
+ }
+
+ /**
+ * Get or assign the index for an entry of a type that contains
+ * a direct value. The type of the given object determines the
+ * type of the desired entry as follows:
+ *
+ * java.lang.String CONSTANT_Utf8
+ * java.lang.Integer CONSTANT_Integer
+ * java.lang.Float CONSTANT_Float
+ * java.lang.Long CONSTANT_Long
+ * java.lang.Double CONSTANT_DOUBLE
+ */
+ private short getValue(Object key) {
+ Short index = map.get(key);
+ if (index != null) {
+ return index.shortValue();
+ } else {
+ if (readOnly) {
+ throw new InternalError(
+ "late constant pool addition: " + key);
+ }
+ short i = addEntry(new ValueEntry(key));
+ map.put(key, i);
+ return i;
+ }
+ }
+
+ /**
+ * Get or assign the index for an entry of a type that contains
+ * references to other constant pool entries.
+ */
+ private short getIndirect(IndirectEntry e) {
+ Short index = map.get(e);
+ if (index != null) {
+ return index.shortValue();
+ } else {
+ if (readOnly) {
+ throw new InternalError("late constant pool addition");
+ }
+ short i = addEntry(e);
+ map.put(e, i);
+ return i;
+ }
+ }
+
+ /**
+ * Entry is the abstact superclass of all constant pool entry types
+ * that can be stored in the "pool" list; its purpose is to define a
+ * common method for writing constant pool entries to a class file.
+ */
+ private abstract static class Entry {
+ public abstract void write(DataOutputStream out)
+ throws IOException;
+ }
+
+ /**
+ * ValueEntry represents a constant pool entry of a type that
+ * contains a direct value (see the comments for the "getValue"
+ * method for a list of such types).
+ *
+ * ValueEntry objects are not used as keys for their entries in the
+ * Map "map", so no useful hashCode or equals methods are defined.
+ */
+ private static class ValueEntry extends Entry {
+ private Object value;
+
+ public ValueEntry(Object value) {
+ this.value = value;
+ }
+
+ public void write(DataOutputStream out) throws IOException {
+ if (value instanceof String) {
+ out.writeByte(CONSTANT_UTF8);
+ out.writeUTF((String) value);
+ } else if (value instanceof Integer) {
+ out.writeByte(CONSTANT_INTEGER);
+ out.writeInt(((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ out.writeByte(CONSTANT_FLOAT);
+ out.writeFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ out.writeByte(CONSTANT_LONG);
+ out.writeLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ out.writeDouble(CONSTANT_DOUBLE);
+ out.writeDouble(((Double) value).doubleValue());
+ } else {
+ throw new InternalError("bogus value entry: " + value);
+ }
+ }
+ }
+
+ /**
+ * IndirectEntry represents a constant pool entry of a type that
+ * references other constant pool entries, i.e., the following types:
+ *
+ * CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
+ * CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
+ * CONSTANT_NameAndType.
+ *
+ * Each of these entry types contains either one or two indexes of
+ * other constant pool entries.
+ *
+ * IndirectEntry objects are used as the keys for their entries in
+ * the Map "map", so the hashCode and equals methods are overridden
+ * to allow matching.
+ */
+ private static class IndirectEntry extends Entry {
+ private int tag;
+ private short index0;
+ private short index1;
+
+ /**
+ * Construct an IndirectEntry for a constant pool entry type
+ * that contains one index of another entry.
+ */
+ public IndirectEntry(int tag, short index) {
+ this.tag = tag;
+ this.index0 = index;
+ this.index1 = 0;
+ }
+
+ /**
+ * Construct an IndirectEntry for a constant pool entry type
+ * that contains two indexes for other entries.
+ */
+ public IndirectEntry(int tag, short index0, short index1) {
+ this.tag = tag;
+ this.index0 = index0;
+ this.index1 = index1;
+ }
+
+ public void write(DataOutputStream out) throws IOException {
+ out.writeByte(tag);
+ out.writeShort(index0);
+ /*
+ * If this entry type contains two indexes, write
+ * out the second, too.
+ */
+ if (tag == CONSTANT_FIELD ||
+ tag == CONSTANT_METHOD ||
+ tag == CONSTANT_INTERFACEMETHOD ||
+ tag == CONSTANT_NAMEANDTYPE)
+ {
+ out.writeShort(index1);
+ }
+ }
+
+ public int hashCode() {
+ return tag + index0 + index1;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof IndirectEntry) {
+ IndirectEntry other = (IndirectEntry) obj;
+ if (tag == other.tag &&
+ index0 == other.index0 && index1 == other.index1)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+ }
+}
--- a/jdk/src/java.base/share/classes/java/math/BigInteger.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/math/BigInteger.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,8 +38,8 @@
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
import jdk.internal.HotSpotIntrinsicCandidate;
/**
--- a/jdk/src/java.base/share/classes/java/net/URI.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/net/URI.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,6 @@
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.CharacterCodingException;
@@ -490,17 +489,17 @@
private transient String path; // null ==> opaque
private transient String query;
- // The remaining fields may be computed on demand
-
- private transient volatile String schemeSpecificPart;
- private transient volatile int hash; // Zero ==> undefined
-
- private transient volatile String decodedUserInfo = null;
- private transient volatile String decodedAuthority = null;
- private transient volatile String decodedPath = null;
- private transient volatile String decodedQuery = null;
- private transient volatile String decodedFragment = null;
- private transient volatile String decodedSchemeSpecificPart = null;
+ // The remaining fields may be computed on demand, which is safe even in
+ // the face of multiple threads racing to initialize them
+ private transient String schemeSpecificPart;
+ private transient int hash; // Zero ==> undefined
+
+ private transient String decodedUserInfo;
+ private transient String decodedAuthority;
+ private transient String decodedPath;
+ private transient String decodedQuery;
+ private transient String decodedFragment;
+ private transient String decodedSchemeSpecificPart;
/**
* The string form of this URI.
@@ -911,8 +910,7 @@
// either more fields or a more-obscure representation.
if ((host != null) || (authority == null))
return this;
- defineString();
- new Parser(string).parse(true);
+ new Parser(toString()).parse(true);
return this;
}
@@ -1144,8 +1142,17 @@
* (never {@code null})
*/
public String getRawSchemeSpecificPart() {
- defineSchemeSpecificPart();
- return schemeSpecificPart;
+ String part = schemeSpecificPart;
+ if (part != null) {
+ return part;
+ }
+ StringBuilder sb = new StringBuilder();
+ appendSchemeSpecificPart(sb, null, getAuthority(), getUserInfo(),
+ host, port, getPath(), getQuery());
+ if (sb.length() == 0) {
+ return null;
+ }
+ return schemeSpecificPart = sb.toString();
}
/**
@@ -1160,9 +1167,11 @@
* (never {@code null})
*/
public String getSchemeSpecificPart() {
- if (decodedSchemeSpecificPart == null)
- decodedSchemeSpecificPart = decode(getRawSchemeSpecificPart());
- return decodedSchemeSpecificPart;
+ String part = decodedSchemeSpecificPart;
+ if (part == null) {
+ decodedSchemeSpecificPart = part = decode(getRawSchemeSpecificPart());
+ }
+ return part;
}
/**
@@ -1193,9 +1202,11 @@
* or {@code null} if the authority is undefined
*/
public String getAuthority() {
- if (decodedAuthority == null)
- decodedAuthority = decode(authority);
- return decodedAuthority;
+ String auth = decodedAuthority;
+ if ((auth == null) && (authority != null)) {
+ decodedAuthority = auth = decode(authority);
+ }
+ return auth;
}
/**
@@ -1223,9 +1234,11 @@
* or {@code null} if the user information is undefined
*/
public String getUserInfo() {
- if ((decodedUserInfo == null) && (userInfo != null))
- decodedUserInfo = decode(userInfo);
- return decodedUserInfo;
+ String user = decodedUserInfo;
+ if ((user == null) && (userInfo != null)) {
+ decodedUserInfo = user = decode(userInfo);
+ }
+ return user;
}
/**
@@ -1307,9 +1320,11 @@
* or {@code null} if the path is undefined
*/
public String getPath() {
- if ((decodedPath == null) && (path != null))
- decodedPath = decode(path);
- return decodedPath;
+ String decoded = decodedPath;
+ if ((decoded == null) && (path != null)) {
+ decodedPath = decoded = decode(path);
+ }
+ return decoded;
}
/**
@@ -1336,9 +1351,11 @@
* or {@code null} if the query is undefined
*/
public String getQuery() {
- if ((decodedQuery == null) && (query != null))
- decodedQuery = decode(query, false);
- return decodedQuery;
+ String decoded = decodedQuery;
+ if ((decoded == null) && (query != null)) {
+ decodedQuery = decoded = decode(query, false);
+ }
+ return decoded;
}
/**
@@ -1365,9 +1382,11 @@
* or {@code null} if the fragment is undefined
*/
public String getFragment() {
- if ((decodedFragment == null) && (fragment != null))
- decodedFragment = decode(fragment, false);
- return decodedFragment;
+ String decoded = decodedFragment;
+ if ((decoded == null) && (fragment != null)) {
+ decodedFragment = decoded = decode(fragment, false);
+ }
+ return decoded;
}
@@ -1453,24 +1472,27 @@
* @return A hash-code value for this URI
*/
public int hashCode() {
- if (hash != 0)
- return hash;
- int h = hashIgnoringCase(0, scheme);
- h = hash(h, fragment);
- if (isOpaque()) {
- h = hash(h, schemeSpecificPart);
- } else {
- h = hash(h, path);
- h = hash(h, query);
- if (host != null) {
- h = hash(h, userInfo);
- h = hashIgnoringCase(h, host);
- h += 1949 * port;
+ int h = hash;
+ if (h == 0) {
+ h = hashIgnoringCase(0, scheme);
+ h = hash(h, fragment);
+ if (isOpaque()) {
+ h = hash(h, schemeSpecificPart);
} else {
- h = hash(h, authority);
+ h = hash(h, path);
+ h = hash(h, query);
+ if (host != null) {
+ h = hash(h, userInfo);
+ h = hashIgnoringCase(h, host);
+ h += 1949 * port;
+ } else {
+ h = hash(h, authority);
+ }
+ }
+ if (h != 0) {
+ hash = h;
}
}
- hash = h;
return h;
}
@@ -1600,8 +1622,59 @@
* @return The string form of this URI
*/
public String toString() {
- defineString();
- return string;
+ String s = string;
+ if (s == null) {
+ s = defineString();
+ }
+ return s;
+ }
+
+ private String defineString() {
+ String s = string;
+ if (s != null) {
+ return s;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ if (scheme != null) {
+ sb.append(scheme);
+ sb.append(':');
+ }
+ if (isOpaque()) {
+ sb.append(schemeSpecificPart);
+ } else {
+ if (host != null) {
+ sb.append("//");
+ if (userInfo != null) {
+ sb.append(userInfo);
+ sb.append('@');
+ }
+ boolean needBrackets = ((host.indexOf(':') >= 0)
+ && !host.startsWith("[")
+ && !host.endsWith("]"));
+ if (needBrackets) sb.append('[');
+ sb.append(host);
+ if (needBrackets) sb.append(']');
+ if (port != -1) {
+ sb.append(':');
+ sb.append(port);
+ }
+ } else if (authority != null) {
+ sb.append("//");
+ sb.append(authority);
+ }
+ if (path != null)
+ sb.append(path);
+ if (query != null) {
+ sb.append('?');
+ sb.append(query);
+ }
+ }
+ if (fragment != null) {
+ sb.append('#');
+ sb.append(fragment);
+ }
+ return string = sb.toString();
}
/**
@@ -1618,8 +1691,7 @@
* charset
*/
public String toASCIIString() {
- defineString();
- return encode(string);
+ return encode(toString());
}
@@ -1825,7 +1897,7 @@
}
}
- private void appendAuthority(StringBuffer sb,
+ private void appendAuthority(StringBuilder sb,
String authority,
String userInfo,
String host,
@@ -1875,7 +1947,7 @@
}
}
- private void appendSchemeSpecificPart(StringBuffer sb,
+ private void appendSchemeSpecificPart(StringBuilder sb,
String opaquePart,
String authority,
String userInfo,
@@ -1916,7 +1988,7 @@
}
}
- private void appendFragment(StringBuffer sb, String fragment) {
+ private void appendFragment(StringBuilder sb, String fragment) {
if (fragment != null) {
sb.append('#');
sb.append(quote(fragment, L_URIC, H_URIC));
@@ -1933,7 +2005,7 @@
String query,
String fragment)
{
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
if (scheme != null) {
sb.append(scheme);
sb.append(':');
@@ -1945,61 +2017,6 @@
return sb.toString();
}
- private void defineSchemeSpecificPart() {
- if (schemeSpecificPart != null) return;
- StringBuffer sb = new StringBuffer();
- appendSchemeSpecificPart(sb, null, getAuthority(), getUserInfo(),
- host, port, getPath(), getQuery());
- if (sb.length() == 0) return;
- schemeSpecificPart = sb.toString();
- }
-
- private void defineString() {
- if (string != null) return;
-
- StringBuilder sb = new StringBuilder();
- if (scheme != null) {
- sb.append(scheme);
- sb.append(':');
- }
- if (isOpaque()) {
- sb.append(schemeSpecificPart);
- } else {
- if (host != null) {
- sb.append("//");
- if (userInfo != null) {
- sb.append(userInfo);
- sb.append('@');
- }
- boolean needBrackets = ((host.indexOf(':') >= 0)
- && !host.startsWith("[")
- && !host.endsWith("]"));
- if (needBrackets) sb.append('[');
- sb.append(host);
- if (needBrackets) sb.append(']');
- if (port != -1) {
- sb.append(':');
- sb.append(port);
- }
- } else if (authority != null) {
- sb.append("//");
- sb.append(authority);
- }
- if (path != null)
- sb.append(path);
- if (query != null) {
- sb.append('?');
- sb.append(query);
- }
- }
- if (fragment != null) {
- sb.append('#');
- sb.append(fragment);
- }
- string = sb.toString();
- }
-
-
// -- Normalization, resolution, and relativization --
// RFC2396 5.2 (6)
@@ -2650,13 +2667,13 @@
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
- private static void appendEscape(StringBuffer sb, byte b) {
+ private static void appendEscape(StringBuilder sb, byte b) {
sb.append('%');
sb.append(hexDigits[(b >> 4) & 0x0f]);
sb.append(hexDigits[(b >> 0) & 0x0f]);
}
- private static void appendEncoded(StringBuffer sb, char c) {
+ private static void appendEncoded(StringBuilder sb, char c) {
ByteBuffer bb = null;
try {
bb = ThreadLocalCoders.encoderFor("UTF-8")
@@ -2677,15 +2694,14 @@
// by the given mask pair
//
private static String quote(String s, long lowMask, long highMask) {
- int n = s.length();
- StringBuffer sb = null;
+ StringBuilder sb = null;
boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0);
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c < '\u0080') {
if (!match(c, lowMask, highMask)) {
if (sb == null) {
- sb = new StringBuffer();
+ sb = new StringBuilder();
sb.append(s, 0, i);
}
appendEscape(sb, (byte)c);
@@ -2697,7 +2713,7 @@
&& (Character.isSpaceChar(c)
|| Character.isISOControl(c))) {
if (sb == null) {
- sb = new StringBuffer();
+ sb = new StringBuilder();
sb.append(s, 0, i);
}
appendEncoded(sb, c);
@@ -2734,7 +2750,7 @@
assert false;
}
- StringBuffer sb = new StringBuffer();
+ StringBuilder sb = new StringBuilder();
while (bb.hasRemaining()) {
int b = bb.get() & 0xff;
if (b >= 0x80)
@@ -2865,12 +2881,6 @@
fail("Expected " + expected, p);
}
- private void failExpecting(String expected, String prior, int p)
- throws URISyntaxException
- {
- fail("Expected " + expected + " following " + prior, p);
- }
-
// -- Simple access to the input string --
--- a/jdk/src/java.base/share/classes/java/net/URL.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/net/URL.java Wed Jan 06 14:54:24 2016 +0000
@@ -310,7 +310,8 @@
* @param host the name of the host.
* @param port the port number on the host.
* @param file the file on the host
- * @exception MalformedURLException if an unknown protocol is specified.
+ * @exception MalformedURLException if an unknown protocol or the port
+ * is a negative number other than -1
* @see java.lang.System#getProperty(java.lang.String)
* @see java.net.URL#setURLStreamHandlerFactory(
* java.net.URLStreamHandlerFactory)
@@ -329,9 +330,9 @@
* name, {@code host} name, and {@code file} name. The
* default port for the specified protocol is used.
* <p>
- * This method is equivalent to calling the four-argument
- * constructor with the arguments being {@code protocol},
- * {@code host}, {@code -1}, and {@code file}.
+ * This constructor is equivalent to the four-argument
+ * constructor with the only difference of using the
+ * default port for the specified protocol.
*
* No validation of the inputs is performed by this constructor.
*
@@ -372,7 +373,8 @@
* @param port the port number on the host.
* @param file the file on the host
* @param handler the stream handler for the URL.
- * @exception MalformedURLException if an unknown protocol is specified.
+ * @exception MalformedURLException if an unknown protocol or the port
+ is a negative number other than -1
* @exception SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
@@ -446,7 +448,9 @@
*
* @param spec the {@code String} to parse as a URL.
* @exception MalformedURLException if no protocol is specified, or an
- * unknown protocol is found, or {@code spec} is {@code null}.
+ * unknown protocol is found, or {@code spec} is {@code null},
+ * or the parsed URL fails to comply with the specific syntax
+ * of the associated protocol.
* @see java.net.URL#URL(java.net.URL, java.lang.String)
*/
public URL(String spec) throws MalformedURLException {
@@ -493,7 +497,9 @@
* @param context the context in which to parse the specification.
* @param spec the {@code String} to parse as a URL.
* @exception MalformedURLException if no protocol is specified, or an
- * unknown protocol is found, or {@code spec} is {@code null}.
+ * unknown protocol is found, or {@code spec} is {@code null},
+ * or the parsed URL fails to comply with the specific syntax
+ * of the associated protocol.
* @see java.net.URL#URL(java.lang.String, java.lang.String,
* int, java.lang.String)
* @see java.net.URLStreamHandler
@@ -513,7 +519,9 @@
* @param spec the {@code String} to parse as a URL.
* @param handler the stream handler for the URL.
* @exception MalformedURLException if no protocol is specified, or an
- * unknown protocol is found, or {@code spec} is {@code null}.
+ * unknown protocol is found, or {@code spec} is {@code null},
+ * or the parsed URL fails to comply with the specific syntax
+ * of the associated protocol.
* @exception SecurityException
* if a security manager exists and its
* {@code checkPermission} method doesn't allow
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -1550,7 +1550,7 @@
}
if (c1 == 0xFF && c2 == 0xD8 && c3 == 0xFF) {
- if (c4 == 0xE0) {
+ if (c4 == 0xE0 || c4 == 0xEE) {
return "image/jpeg";
}
@@ -1565,10 +1565,6 @@
c11 == 0)) {
return "image/jpeg";
}
-
- if (c4 == 0xEE) {
- return "image/jpg";
- }
}
if (c1 == 0xD0 && c2 == 0xCF && c3 == 0x11 && c4 == 0xE0 &&
--- a/jdk/src/java.base/share/classes/java/nio/Bits.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,9 +25,7 @@
package java.nio;
-import java.security.AccessController;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.LongAdder;
import jdk.internal.misc.JavaNioAccess;
import jdk.internal.misc.JavaLangRefAccess;
@@ -603,7 +601,8 @@
private static final AtomicLong reservedMemory = new AtomicLong();
private static final AtomicLong totalCapacity = new AtomicLong();
private static final AtomicLong count = new AtomicLong();
- private static volatile boolean memoryLimitSet = false;
+ private static volatile boolean memoryLimitSet;
+
// max. number of sleeps during try-reserving with exponentially
// increasing delay before throwing OutOfMemoryError:
// 1, 2, 4, 8, 16, 32, 64, 128, 256 (total 511 ms ~ 0.5 s)
--- a/jdk/src/java.base/share/classes/java/nio/channels/SelectionKey.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/nio/channels/SelectionKey.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,8 +26,6 @@
package java.nio.channels;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-import java.io.IOException;
-
/**
* A token representing the registration of a {@link SelectableChannel} with a
@@ -363,7 +361,7 @@
// -- Attachments --
- private volatile Object attachment = null;
+ private volatile Object attachment;
private static final AtomicReferenceFieldUpdater<SelectionKey,Object>
attachmentUpdater = AtomicReferenceFieldUpdater.newUpdater(
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,11 +29,7 @@
package java.nio.channels.spi;
import java.io.IOException;
-import java.lang.reflect.Method;
-import java.lang.reflect.InvocationTargetException;
import java.nio.channels.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import jdk.internal.misc.SharedSecrets;
import sun.nio.ch.Interruptible;
@@ -90,7 +86,7 @@
{
private final Object closeLock = new Object();
- private volatile boolean open = true;
+ private volatile boolean closed;
/**
* Initializes a new instance of this class.
@@ -110,9 +106,9 @@
*/
public final void close() throws IOException {
synchronized (closeLock) {
- if (!open)
+ if (closed)
return;
- open = false;
+ closed = true;
implCloseChannel();
}
}
@@ -136,7 +132,7 @@
protected abstract void implCloseChannel() throws IOException;
public final boolean isOpen() {
- return open;
+ return !closed;
}
@@ -158,9 +154,9 @@
interruptor = new Interruptible() {
public void interrupt(Thread target) {
synchronized (closeLock) {
- if (!open)
+ if (closed)
return;
- open = false;
+ closed = true;
interrupted = target;
try {
AbstractInterruptibleChannel.this.implCloseChannel();
@@ -202,7 +198,7 @@
this.interrupted = null;
throw new ClosedByInterruptException();
}
- if (!completed && !open)
+ if (!completed && closed)
throw new AsynchronousCloseException();
}
--- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Wed Jan 06 14:54:24 2016 +0000
@@ -276,7 +276,7 @@
/* -- Static methods -- */
- private static volatile String bugLevel = null;
+ private static volatile String bugLevel;
static boolean atBugLevel(String bl) { // package-private
String level = bugLevel;
@@ -324,8 +324,8 @@
// Cache of the most-recently-returned charsets,
// along with the names that were used to find them
//
- private static volatile Object[] cache1 = null; // "Level 1" cache
- private static volatile Object[] cache2 = null; // "Level 2" cache
+ private static volatile Object[] cache1; // "Level 1" cache
+ private static volatile Object[] cache2; // "Level 2" cache
private static void cache(String charsetName, Charset cs) {
cache2 = cache1;
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java Wed Jan 06 14:54:24 2016 +0000
@@ -124,7 +124,7 @@
private String algorithm;
// Seed Generator
- private static volatile SecureRandom seedGenerator = null;
+ private static volatile SecureRandom seedGenerator;
/**
* Constructs a secure random number generator (RNG) implementing the
@@ -522,10 +522,12 @@
* @see #setSeed
*/
public static byte[] getSeed(int numBytes) {
- if (seedGenerator == null) {
- seedGenerator = new SecureRandom();
+ SecureRandom seedGen = seedGenerator;
+ if (seedGen == null) {
+ seedGen = new SecureRandom();
+ seedGenerator = seedGen;
}
- return seedGenerator.generateSeed(numBytes);
+ return seedGen.generateSeed(numBytes);
}
/**
--- a/jdk/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/security/cert/PolicyQualifierInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,7 +27,7 @@
import java.io.IOException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.DerValue;
/**
--- a/jdk/src/java.base/share/classes/java/security/cert/X509CertSelector.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/security/cert/X509CertSelector.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,7 @@
import java.util.*;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.Debug;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
--- a/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/text/DateFormatSymbols.java Wed Jan 06 14:54:24 2016 +0000
@@ -630,7 +630,9 @@
hashCode = 11 * hashCode + Arrays.hashCode(ampms);
hashCode = 11 * hashCode + Arrays.deepHashCode(getZoneStringsWrapper());
hashCode = 11 * hashCode + Objects.hashCode(localPatternChars);
- cachedHashCode = hashCode;
+ if (hashCode != 0) {
+ cachedHashCode = hashCode;
+ }
}
return hashCode;
@@ -670,12 +672,12 @@
private static final ConcurrentMap<Locale, SoftReference<DateFormatSymbols>> cachedInstances
= new ConcurrentHashMap<>(3);
- private transient int lastZoneIndex = 0;
+ private transient int lastZoneIndex;
/**
* Cached hash code
*/
- transient volatile int cachedHashCode = 0;
+ transient volatile int cachedHashCode;
private void initializeData(Locale desiredLocale) {
locale = desiredLocale;
--- a/jdk/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,14 +42,8 @@
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.text.spi.DecimalFormatSymbolsProvider;
-import java.util.ArrayList;
import java.util.Currency;
-import java.util.List;
import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -875,7 +869,7 @@
// currency; only the ISO code is serialized.
private transient Currency currency;
- private transient volatile boolean currencyInitialized = false;
+ private transient volatile boolean currencyInitialized;
// Proclaim JDK 1.1 FCS compatibility
static final long serialVersionUID = 5772796243397350300L;
--- a/jdk/src/java.base/share/classes/java/text/DigitList.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/text/DigitList.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
-import sun.misc.FloatingDecimal;
+import jdk.internal.math.FloatingDecimal;
/**
* Digit List. Private to DecimalFormat.
--- a/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/text/SimpleDateFormat.java Wed Jan 06 14:54:24 2016 +0000
@@ -1856,6 +1856,7 @@
if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
patternCharIndex == PATTERN_HOUR1 ||
(patternCharIndex == PATTERN_MONTH && count <= 2) ||
+ (patternCharIndex == PATTERN_MONTH_STANDALONE && count <= 2) ||
patternCharIndex == PATTERN_YEAR ||
patternCharIndex == PATTERN_WEEK_YEAR) {
// It would be good to unify this with the obeyCount logic below,
@@ -1976,6 +1977,20 @@
}
break parsing;
+ case PATTERN_MONTH_STANDALONE: // 'L'
+ if (count <= 2) {
+ // Don't want to parse the month if it is a string
+ // while pattern uses numeric style: L or LL
+ //[we computed 'value' above.]
+ calb.set(Calendar.MONTH, value - 1);
+ return pos.index;
+ }
+ Map<String, Integer> maps = getDisplayNamesMap(field, locale);
+ if ((index = matchString(text, start, field, maps, calb)) > 0) {
+ return index;
+ }
+ break parsing;
+
case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59
if (!isLenient()) {
// Validate the hour value in non-lenient
--- a/jdk/src/java.base/share/classes/java/time/Duration.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/Duration.java Wed Jan 06 14:54:24 2016 +0000
@@ -997,6 +997,24 @@
}
/**
+ * Returns number of whole times a specified Duration occurs within this Duration.
+ * <p>
+ * This instance is immutable and unaffected by this method call.
+ *
+ * @param divisor the value to divide the duration by, positive or negative, not null
+ * @return number of whole times, rounded toward zero, a specified
+ * {@code Duration} occurs within this Duration, may be negative
+ * @throws ArithmeticException if the divisor is zero, or if numeric overflow occurs
+ * @since 9
+ */
+ public long dividedBy(Duration divisor) {
+ Objects.requireNonNull(divisor, "divisor");
+ BigDecimal dividendBigD = toBigDecimalSeconds();
+ BigDecimal divisorBigD = divisor.toBigDecimalSeconds();
+ return dividendBigD.divideToIntegralValue(divisorBigD).longValueExact();
+ }
+
+ /**
* Converts this duration to the total length in seconds and
* fractional nanoseconds expressed as a {@code BigDecimal}.
*
--- a/jdk/src/java.base/share/classes/java/time/LocalDate.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/LocalDate.java Wed Jan 06 14:54:24 2016 +0000
@@ -147,6 +147,10 @@
* This could be used by an application as a "far future" date.
*/
public static final LocalDate MAX = LocalDate.of(Year.MAX_VALUE, 12, 31);
+ /**
+ * The epoch year {@code LocalDate}, '1970-01-01'.
+ */
+ public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1);
/**
* Serialization version.
@@ -1864,6 +1868,29 @@
return total - DAYS_0000_TO_1970;
}
+ /**
+ * Converts this {@code LocalDate} to the number of seconds since the epoch
+ * of 1970-01-01T00:00:00Z.
+ * <p>
+ * This combines this local date with the specified time and
+ * offset to calculate the epoch-second value, which is the
+ * number of elapsed seconds from 1970-01-01T00:00:00Z.
+ * Instants on the time-line after the epoch are positive, earlier
+ * are negative.
+ *
+ * @param time the local time, not null
+ * @param offset the zone offset, not null
+ * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
+ * @since 9
+ */
+ public long toEpochSecond(LocalTime time, ZoneOffset offset) {
+ Objects.requireNonNull(time, "time");
+ Objects.requireNonNull(offset, "offset");
+ long secs = toEpochDay() * SECONDS_PER_DAY + time.toSecondOfDay();
+ secs -= offset.getTotalSeconds();
+ return secs;
+ }
+
//-----------------------------------------------------------------------
/**
* Compares this date to another date.
--- a/jdk/src/java.base/share/classes/java/time/LocalTime.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/LocalTime.java Wed Jan 06 14:54:24 2016 +0000
@@ -1490,6 +1490,30 @@
return total;
}
+ /**
+ * Converts this {@code LocalTime} to the number of seconds since the epoch
+ * of 1970-01-01T00:00:00Z.
+ * <p>
+ * This combines this local time with the specified date and
+ * offset to calculate the epoch-second value, which is the
+ * number of elapsed seconds from 1970-01-01T00:00:00Z.
+ * Instants on the time-line after the epoch are positive, earlier
+ * are negative.
+ *
+ * @param date the local date, not null
+ * @param offset the zone offset, not null
+ * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
+ * @since 9
+ */
+ public long toEpochSecond(LocalDate date, ZoneOffset offset) {
+ Objects.requireNonNull(date, "date");
+ Objects.requireNonNull(offset, "offset");
+ long epochDay = date.toEpochDay();
+ long secs = epochDay * 86400 + toSecondOfDay();
+ secs -= offset.getTotalSeconds();
+ return secs;
+ }
+
//-----------------------------------------------------------------------
/**
* Compares this time to another time.
--- a/jdk/src/java.base/share/classes/java/time/OffsetTime.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/OffsetTime.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -1232,6 +1232,28 @@
return nod - offsetNanos;
}
+ /**
+ * Converts this {@code OffsetTime} to the number of seconds since the epoch
+ * of 1970-01-01T00:00:00Z.
+ * <p>
+ * This combines this offset time with the specified date to calculate the
+ * epoch-second value, which is the number of elapsed seconds from
+ * 1970-01-01T00:00:00Z.
+ * Instants on the time-line after the epoch are positive, earlier
+ * are negative.
+ *
+ * @param date the localdate, not null
+ * @return the number of seconds since the epoch of 1970-01-01T00:00:00Z, may be negative
+ * @since 9
+ */
+ public long toEpochSecond(LocalDate date) {
+ Objects.requireNonNull(date, "date");
+ long epochDay = date.toEpochDay();
+ long secs = epochDay * 86400 + time.toSecondOfDay();
+ secs -= offset.getTotalSeconds();
+ return secs;
+ }
+
//-----------------------------------------------------------------------
/**
* Compares this {@code OffsetTime} to another time.
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -80,6 +80,7 @@
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
+import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
@@ -473,6 +474,17 @@
* day-of-week was valid for the date.
* <li>If an {@linkplain #parsedExcessDays() excess number of days}
* was parsed then it is added to the date if a date is available.
+ * <li> If a second-based field is present, but {@code LocalTime} was not parsed,
+ * then the resolver ensures that milli, micro and nano second values are
+ * available to meet the contract of {@link ChronoField}.
+ * These will be set to zero if missing.
+ * <li>If both date and time were parsed and either an offset or zone is present,
+ * the field {@link ChronoField#INSTANT_SECONDS} is created.
+ * If an offset was parsed then the offset will be combined with the
+ * {@code LocalDateTime} to form the instant, with any zone ignored.
+ * If a {@code ZoneId} was parsed without an offset then the zone will be
+ * combined with the {@code LocalDateTime} to form the instant using the rules
+ * of {@link ChronoLocalDateTime#atZone(ZoneId)}.
* </ol>
*
* @implSpec
--- a/jdk/src/java.base/share/classes/java/time/format/Parsed.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/time/format/Parsed.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -594,15 +594,16 @@
private void resolveInstant() {
// add instant seconds if we have date, time and zone
+ // Offset (if present) will be given priority over the zone.
if (date != null && time != null) {
- if (zone != null) {
- long instant = date.atTime(time).atZone(zone).getLong(ChronoField.INSTANT_SECONDS);
+ Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
+ if (offsetSecs != null) {
+ ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
+ long instant = date.atTime(time).atZone(offset).toEpochSecond();
fieldValues.put(INSTANT_SECONDS, instant);
} else {
- Long offsetSecs = fieldValues.get(OFFSET_SECONDS);
- if (offsetSecs != null) {
- ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue());
- long instant = date.atTime(time).atZone(offset).getLong(ChronoField.INSTANT_SECONDS);
+ if (zone != null) {
+ long instant = date.atTime(time).atZone(zone).toEpochSecond();
fieldValues.put(INSTANT_SECONDS, instant);
}
}
--- a/jdk/src/java.base/share/classes/java/util/AbstractMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/AbstractMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -304,9 +304,28 @@
* Each of these fields are initialized to contain an instance of the
* appropriate view the first time this view is requested. The views are
* stateless, so there's no reason to create more than one of each.
+ *
+ * <p>Since there is no synchronization performed while accessing these fields,
+ * it is expected that java.util.Map view classes using these fields have
+ * no non-final fields (or any fields at all except for outer-this). Adhering
+ * to this rule would make the races on these fields benign.
+ *
+ * <p>It is also imperative that implementations read the field only once,
+ * as in:
+ *
+ * <pre> {@code
+ * public Set<K> keySet() {
+ * Set<K> ks = keySet; // single racy read
+ * if (ks == null) {
+ * ks = new KeySet();
+ * keySet = ks;
+ * }
+ * return ks;
+ * }
+ *}</pre>
*/
- transient volatile Set<K> keySet;
- transient volatile Collection<V> values;
+ transient Set<K> keySet;
+ transient Collection<V> values;
/**
* {@inheritDoc}
@@ -325,8 +344,9 @@
* method will not all return the same set.
*/
public Set<K> keySet() {
- if (keySet == null) {
- keySet = new AbstractSet<K>() {
+ Set<K> ks = keySet;
+ if (ks == null) {
+ ks = new AbstractSet<K>() {
public Iterator<K> iterator() {
return new Iterator<K>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -361,8 +381,9 @@
return AbstractMap.this.containsKey(k);
}
};
+ keySet = ks;
}
- return keySet;
+ return ks;
}
/**
@@ -382,8 +403,9 @@
* method will not all return the same collection.
*/
public Collection<V> values() {
- if (values == null) {
- values = new AbstractCollection<V>() {
+ Collection<V> vals = values;
+ if (vals == null) {
+ vals = new AbstractCollection<V>() {
public Iterator<V> iterator() {
return new Iterator<V>() {
private Iterator<Entry<K,V>> i = entrySet().iterator();
@@ -418,8 +440,9 @@
return AbstractMap.this.containsValue(v);
}
};
+ values = vals;
}
- return values;
+ return vals;
}
public abstract Set<Entry<K,V>> entrySet();
--- a/jdk/src/java.base/share/classes/java/util/Collections.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/Collections.java Wed Jan 06 14:54:24 2016 +0000
@@ -5530,7 +5530,7 @@
* @since 1.6
*/
public static <T> Queue<T> asLifoQueue(Deque<T> deque) {
- return new AsLIFOQueue<>(deque);
+ return new AsLIFOQueue<>(Objects.requireNonNull(deque));
}
/**
--- a/jdk/src/java.base/share/classes/java/util/EnumMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/EnumMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -380,10 +380,11 @@
*/
public Set<K> keySet() {
Set<K> ks = keySet;
- if (ks != null)
- return ks;
- else
- return keySet = new KeySet();
+ if (ks == null) {
+ ks = new KeySet();
+ keySet = ks;
+ }
+ return ks;
}
private class KeySet extends AbstractSet<K> {
@@ -418,10 +419,11 @@
*/
public Collection<V> values() {
Collection<V> vs = values;
- if (vs != null)
- return vs;
- else
- return values = new Values();
+ if (vs == null) {
+ vs = new Values();
+ values = vs;
+ }
+ return vs;
}
private class Values extends AbstractCollection<V> {
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -60,8 +60,8 @@
import java.time.temporal.TemporalQueries;
import java.time.temporal.UnsupportedTemporalTypeException;
-import sun.misc.DoubleConsts;
-import sun.misc.FormattedFloatingDecimal;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FormattedFloatingDecimal;
/**
* An interpreter for printf-style format strings. This class provides support
--- a/jdk/src/java.base/share/classes/java/util/HashMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/HashMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -902,8 +902,12 @@
* @return a set view of the keys contained in this map
*/
public Set<K> keySet() {
- Set<K> ks;
- return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
+ Set<K> ks = keySet;
+ if (ks == null) {
+ ks = new KeySet();
+ keySet = ks;
+ }
+ return ks;
}
final class KeySet extends AbstractSet<K> {
@@ -949,8 +953,12 @@
* @return a view of the values contained in this map
*/
public Collection<V> values() {
- Collection<V> vs;
- return (vs = values) == null ? (values = new Values()) : vs;
+ Collection<V> vs = values;
+ if (vs == null) {
+ vs = new Values();
+ values = vs;
+ }
+ return vs;
}
final class Values extends AbstractCollection<V> {
--- a/jdk/src/java.base/share/classes/java/util/IdentityHashMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/IdentityHashMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -964,10 +964,11 @@
*/
public Set<K> keySet() {
Set<K> ks = keySet;
- if (ks != null)
- return ks;
- else
- return keySet = new KeySet();
+ if (ks == null) {
+ ks = new KeySet();
+ keySet = ks;
+ }
+ return ks;
}
private class KeySet extends AbstractSet<K> {
@@ -1069,10 +1070,11 @@
*/
public Collection<V> values() {
Collection<V> vs = values;
- if (vs != null)
- return vs;
- else
- return values = new Values();
+ if (vs == null) {
+ vs = new Values();
+ values = vs;
+ }
+ return vs;
}
private class Values extends AbstractCollection<V> {
--- a/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/LinkedHashMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -528,8 +528,12 @@
* @return a set view of the keys contained in this map
*/
public Set<K> keySet() {
- Set<K> ks;
- return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
+ Set<K> ks = keySet;
+ if (ks == null) {
+ ks = new LinkedKeySet();
+ keySet = ks;
+ }
+ return ks;
}
final class LinkedKeySet extends AbstractSet<K> {
@@ -577,8 +581,12 @@
* @return a view of the values contained in this map
*/
public Collection<V> values() {
- Collection<V> vs;
- return (vs = values) == null ? (values = new LinkedValues()) : vs;
+ Collection<V> vs = values;
+ if (vs == null) {
+ vs = new LinkedValues();
+ values = vs;
+ }
+ return vs;
}
final class LinkedValues extends AbstractCollection<V> {
--- a/jdk/src/java.base/share/classes/java/util/Locale.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/Locale.java Wed Jan 06 14:54:24 2016 +0000
@@ -62,7 +62,6 @@
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
import sun.util.locale.provider.LocaleServiceProviderPool;
-import sun.util.locale.provider.ResourceBundleBasedAdapter;
/**
* A <code>Locale</code> object represents a specific geographical, political,
@@ -2016,11 +2015,11 @@
/**
* Calculated hashcode
*/
- private transient volatile int hashCodeValue = 0;
+ private transient volatile int hashCodeValue;
private static volatile Locale defaultLocale = initDefault();
- private static volatile Locale defaultDisplayLocale = null;
- private static volatile Locale defaultFormatLocale = null;
+ private static volatile Locale defaultDisplayLocale;
+ private static volatile Locale defaultFormatLocale;
private transient volatile String languageTag;
@@ -2207,9 +2206,9 @@
baseLocale.getRegion(), baseLocale.getVariant(), localeExtensions);
}
- private static volatile String[] isoLanguages = null;
+ private static volatile String[] isoLanguages;
- private static volatile String[] isoCountries = null;
+ private static volatile String[] isoCountries;
private static String convertOldISOCodes(String language) {
// we accept both the old and the new ISO codes for the languages whose ISO
@@ -2851,7 +2850,7 @@
private final String range;
private final double weight;
- private volatile int hash = 0;
+ private volatile int hash;
/**
* Constructs a {@code LanguageRange} using the given {@code range}.
@@ -3108,14 +3107,17 @@
*/
@Override
public int hashCode() {
- if (hash == 0) {
- int result = 17;
- result = 37*result + range.hashCode();
+ int h = hash;
+ if (h == 0) {
+ h = 17;
+ h = 37*h + range.hashCode();
long bitsWeight = Double.doubleToLongBits(weight);
- result = 37*result + (int)(bitsWeight ^ (bitsWeight >>> 32));
- hash = result;
+ h = 37*h + (int)(bitsWeight ^ (bitsWeight >>> 32));
+ if (h != 0) {
+ hash = h;
+ }
}
- return hash;
+ return h;
}
/**
--- a/jdk/src/java.base/share/classes/java/util/Map.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/Map.java Wed Jan 06 14:54:24 2016 +0000
@@ -1670,9 +1670,9 @@
*/
@SafeVarargs
@SuppressWarnings("varargs")
- static <K, V> Map<K, V> ofEntries(Entry<K, V>... entries) {
+ static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
Map<K, V> map = new HashMap<>(entries.length * 4 / 3 + 1); // throws NPE if entries is null
- for (Entry<K, V> e : entries) {
+ for (Entry<? extends K, ? extends V> e : entries) {
// next line throws NPE if e is null
map.put(Objects.requireNonNull(e.getKey()), Objects.requireNonNull(e.getValue()));
}
--- a/jdk/src/java.base/share/classes/java/util/TreeMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/TreeMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -852,7 +852,11 @@
*/
public Collection<V> values() {
Collection<V> vs = values;
- return (vs != null) ? vs : (values = new Values());
+ if (vs == null) {
+ vs = new Values();
+ values = vs;
+ }
+ return vs;
}
/**
--- a/jdk/src/java.base/share/classes/java/util/WeakHashMap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/WeakHashMap.java Wed Jan 06 14:54:24 2016 +0000
@@ -866,7 +866,11 @@
*/
public Set<K> keySet() {
Set<K> ks = keySet;
- return (ks != null ? ks : (keySet = new KeySet()));
+ if (ks == null) {
+ ks = new KeySet();
+ keySet = ks;
+ }
+ return ks;
}
private class KeySet extends AbstractSet<K> {
@@ -915,7 +919,11 @@
*/
public Collection<V> values() {
Collection<V> vs = values;
- return (vs != null) ? vs : (values = new Values());
+ if (vs == null) {
+ vs = new Values();
+ values = vs;
+ }
+ return vs;
}
private class Values extends AbstractCollection<V> {
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed Jan 06 14:54:24 2016 +0000
@@ -203,7 +203,10 @@
return man;
}
- private native String[] getMetaInfEntryNames();
+ private String[] getMetaInfEntryNames() {
+ return jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess()
+ .getMetaInfEntryNames((ZipFile)this);
+ }
/**
* Returns the {@code JarEntry} for the given entry name or
--- a/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/regex/Pattern.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -950,7 +950,7 @@
* Boolean indicating this Pattern is compiled; this is necessary in order
* to lazily compile deserialized Patterns.
*/
- private transient volatile boolean compiled = false;
+ private transient volatile boolean compiled;
/**
* The normalized pattern string.
@@ -1332,7 +1332,6 @@
localCount = 0;
// if length > 0, the Pattern is lazily compiled
- compiled = false;
if (pattern.length() == 0) {
root = new Start(lastAccept);
matchRoot = lastAccept;
@@ -1377,7 +1376,6 @@
* equivalences of the characters.
*/
private void normalize() {
- boolean inCharClass = false;
int lastCodePoint = -1;
// Convert pattern into normalized form
@@ -1551,7 +1549,6 @@
// offset maintains the index in code units.
loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
len = countChars(input, offset, 1);
- boolean skip = false;
for(int y=x-1; y>=0; y--) {
if (combClass[y] == combClass[x]) {
continue loop;
@@ -1566,8 +1563,7 @@
temp[index++] = prefix + sre;
}
String[] result = new String[index];
- for (int x=0; x<index; x++)
- result[x] = temp[x];
+ System.arraycopy(temp, 0, result, 0, index);
return result;
}
@@ -1742,9 +1738,11 @@
}
Map<String, Integer> namedGroups() {
- if (namedGroups == null)
- namedGroups = new HashMap<>(2);
- return namedGroups;
+ Map<String, Integer> groups = namedGroups;
+ if (groups == null) {
+ namedGroups = groups = new HashMap<>(2);
+ }
+ return groups;
}
/**
@@ -5814,7 +5812,7 @@
*/
public Stream<String> splitAsStream(final CharSequence input) {
class MatcherIterator implements Iterator<String> {
- private final Matcher matcher;
+ private Matcher matcher;
// The start position of the next sub-sequence of input
// when current == input.length there are no more elements
private int current;
@@ -5823,14 +5821,6 @@
// > 0 if there are N next empty elements
private int emptyElementCount;
- MatcherIterator() {
- this.matcher = matcher(input);
- // If the input is an empty string then the result can only be a
- // stream of the input. Induce that by setting the empty
- // element count to 1
- this.emptyElementCount = input.length() == 0 ? 1 : 0;
- }
-
public String next() {
if (!hasNext())
throw new NoSuchElementException();
@@ -5846,6 +5836,13 @@
}
public boolean hasNext() {
+ if (matcher == null) {
+ matcher = matcher(input);
+ // If the input is an empty string then the result can only be a
+ // stream of the input. Induce that by setting the empty
+ // element count to 1
+ emptyElementCount = input.length() == 0 ? 1 : 0;
+ }
if (nextElement != null || emptyElementCount > 0)
return true;
--- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java Wed Jan 06 14:54:24 2016 +0000
@@ -434,7 +434,7 @@
* stream returned by mapper
* @return a collector which applies the mapping function to the input
* elements and provides the flat mapped results to the downstream collector
- * @since 1.9
+ * @since 9
*/
public static <T, U, A, R>
Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
@@ -452,6 +452,53 @@
}
/**
+ * Adapts a {@code Collector} to one accepting elements of the same type
+ * {@code T} by applying the predicate to each input element and only
+ * accumulating if the predicate returns {@code true}.
+ *
+ * @apiNote
+ * The {@code filtering()} collectors are most useful when used in a
+ * multi-level reduction, such as downstream of a {@code groupingBy} or
+ * {@code partitioningBy}. For example, given a stream of
+ * {@code Employee}, to accumulate the employees in each department that have a
+ * salary above a certain threshold:
+ * <pre>{@code
+ * Map<Department, Set<Employee>> wellPaidEmployeesByDepartment
+ * = employees.stream().collect(groupingBy(Employee::getDepartment,
+ * filtering(e -> e.getSalary() > 2000, toSet())));
+ * }</pre>
+ * A filtering collector differs from a stream's {@code filter()} operation.
+ * In this example, suppose there are no employees whose salary is above the
+ * threshold in some department. Using a filtering collector as shown above
+ * would result in a mapping from that department to an empty {@code Set}.
+ * If a stream {@code filter()} operation were done instead, there would be
+ * no mapping for that department at all.
+ *
+ * @param <T> the type of the input elements
+ * @param <A> intermediate accumulation type of the downstream collector
+ * @param <R> result type of collector
+ * @param predicate a predicate to be applied to the input elements
+ * @param downstream a collector which will accept values that match the
+ * predicate
+ * @return a collector which applies the predicate to the input elements
+ * and provides matching elements to the downstream collector
+ * @since 9
+ */
+ public static <T, A, R>
+ Collector<T, ?, R> filtering(Predicate<? super T> predicate,
+ Collector<? super T, A, R> downstream) {
+ BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
+ return new CollectorImpl<>(downstream.supplier(),
+ (r, t) -> {
+ if (predicate.test(t)) {
+ downstreamAccumulator.accept(r, t);
+ }
+ },
+ downstream.combiner(), downstream.finisher(),
+ downstream.characteristics());
+ }
+
+ /**
* Adapts a {@code Collector} to perform an additional finishing
* transformation. For example, one could adapt the {@link #toList()}
* collector to always produce an immutable list with:
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipCoder.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,7 +43,7 @@
final class ZipCoder {
- String toString(byte[] ba, int length) {
+ String toString(byte[] ba, int off, int length) {
CharsetDecoder cd = decoder().reset();
int len = (int)(length * cd.maxCharsPerByte());
char[] ca = new char[len];
@@ -53,12 +53,12 @@
// CodingErrorAction.REPLACE mode. ZipCoder uses
// REPORT mode.
if (isUTF8 && cd instanceof ArrayDecoder) {
- int clen = ((ArrayDecoder)cd).decode(ba, 0, length, ca);
+ int clen = ((ArrayDecoder)cd).decode(ba, off, length, ca);
if (clen == -1) // malformed
throw new IllegalArgumentException("MALFORMED");
return new String(ca, 0, clen);
}
- ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
+ ByteBuffer bb = ByteBuffer.wrap(ba, off, length);
CharBuffer cb = CharBuffer.wrap(ca);
CoderResult cr = cd.decode(bb, cb, true);
if (!cr.isUnderflow())
@@ -69,8 +69,12 @@
return new String(ca, 0, cb.position());
}
+ String toString(byte[] ba, int length) {
+ return toString(ba, 0, length);
+ }
+
String toString(byte[] ba) {
- return toString(ba, ba.length);
+ return toString(ba, 0, ba.length);
}
byte[] getBytes(String s) {
@@ -111,13 +115,16 @@
return utf8.getBytes(s);
}
+ String toStringUTF8(byte[] ba, int len) {
+ return toStringUTF8(ba, 0, len);
+ }
- String toStringUTF8(byte[] ba, int len) {
+ String toStringUTF8(byte[] ba, int off, int len) {
if (isUTF8)
- return toString(ba, len);
+ return toString(ba, off, len);
if (utf8 == null)
utf8 = new ZipCoder(StandardCharsets.UTF_8);
- return utf8.toString(ba, len);
+ return utf8.toString(ba, off, len);
}
boolean isUTF8() {
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipFile.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,14 +30,22 @@
import java.io.IOException;
import java.io.EOFException;
import java.io.File;
+import java.io.RandomAccessFile;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.Path;
+import java.nio.file.Files;
+
import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Objects;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Spliterators;
@@ -47,7 +55,9 @@
import jdk.internal.misc.JavaUtilZipFileAccess;
import jdk.internal.misc.SharedSecrets;
+import static java.util.zip.ZipConstants.*;
import static java.util.zip.ZipConstants64.*;
+import static java.util.zip.ZipUtils.*;
/**
* This class is used to read entries from a zip file.
@@ -60,11 +70,11 @@
*/
public
class ZipFile implements ZipConstants, Closeable {
- private long jzfile; // address of jzfile data
+
private final String name; // zip file name
- private final int total; // total number of entries
- private final boolean locsig; // if zip file starts with LOCSIG (usually true)
- private volatile boolean closeRequested = false;
+ private volatile boolean closeRequested;
+ private Source zsrc;
+ private ZipCoder zc;
private static final int STORED = ZipEntry.STORED;
private static final int DEFLATED = ZipEntry.DEFLATED;
@@ -83,23 +93,6 @@
*/
public static final int OPEN_DELETE = 0x4;
- static {
- /* Zip library is loaded from System.initializeSystemClass */
- initIDs();
- }
-
- private static native void initIDs();
-
- private static final boolean usemmap;
-
- static {
- // A system prpperty to disable mmap use to avoid vm crash when
- // in-use zip file is accidently overwritten by others.
- String prop = sun.misc.VM.getSavedProperty("sun.zip.disableMemoryMapping");
- usemmap = (prop == null ||
- !(prop.length() == 0 || prop.equalsIgnoreCase("true")));
- }
-
/**
* Opens a zip file for reading.
*
@@ -165,8 +158,6 @@
this(file, OPEN_READ);
}
- private ZipCoder zc;
-
/**
* Opens a new {@code ZipFile} to read from the specified
* {@code File} object in the specified mode. The mode argument
@@ -214,16 +205,13 @@
sm.checkDelete(name);
}
}
- if (charset == null)
- throw new NullPointerException("charset is null");
+ Objects.requireNonNull(charset, "charset");
this.zc = ZipCoder.get(charset);
+ this.name = name;
long t0 = System.nanoTime();
- jzfile = open(name, mode, file.lastModified(), usemmap);
+ this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
sun.misc.PerfCounter.getZipFileCount().increment();
- this.name = name;
- this.total = getTotal(jzfile);
- this.locsig = startsWithLOC(jzfile);
}
/**
@@ -257,6 +245,7 @@
/**
* Opens a ZIP file for reading given the specified File object.
+ *
* @param file the ZIP file to be opened for reading
* @param charset
* The {@linkplain java.nio.charset.Charset charset} to be
@@ -287,10 +276,10 @@
public String getComment() {
synchronized (this) {
ensureOpen();
- byte[] bcomm = getCommentBytes(jzfile);
- if (bcomm == null)
+ if (zsrc.comment == null) {
return null;
- return zc.toString(bcomm, bcomm.length);
+ }
+ return zc.toString(zsrc.comment);
}
}
@@ -303,38 +292,28 @@
* @throws IllegalStateException if the zip file has been closed
*/
public ZipEntry getEntry(String name) {
- if (name == null) {
- throw new NullPointerException("name");
- }
- long jzentry = 0;
+
+ Objects.requireNonNull(name, "name");
synchronized (this) {
ensureOpen();
- jzentry = getEntry(jzfile, zc.getBytes(name), true);
- if (jzentry != 0) {
- ZipEntry ze = getZipEntry(name, jzentry);
- freeEntry(jzfile, jzentry);
- return ze;
+ int pos = zsrc.getEntryPos(zc.getBytes(name), true);
+ if (pos != -1) {
+ return getZipEntry(name, pos);
}
}
return null;
}
- private static native long getEntry(long jzfile, byte[] name,
- boolean addSlash);
-
- // freeEntry releases the C jzentry struct.
- private static native void freeEntry(long jzfile, long jzentry);
-
- // the outstanding inputstreams that need to be closed,
+ // The outstanding inputstreams that need to be closed,
// mapped to the inflater objects they use.
private final Map<InputStream, Inflater> streams = new WeakHashMap<>();
/**
* Returns an input stream for reading the contents of the specified
* zip file entry.
- *
- * <p> Closing this ZIP file will, in turn, close all input
- * streams that have been returned by invocations of this method.
+ * <p>
+ * Closing this ZIP file will, in turn, close all input streams that
+ * have been returned by invocations of this method.
*
* @param entry the zip file entry
* @return the input stream for reading the contents of the specified
@@ -344,37 +323,38 @@
* @throws IllegalStateException if the zip file has been closed
*/
public InputStream getInputStream(ZipEntry entry) throws IOException {
- if (entry == null) {
- throw new NullPointerException("entry");
- }
- long jzentry = 0;
+ Objects.requireNonNull(entry, "entry");
+ int pos = -1;
ZipFileInputStream in = null;
synchronized (this) {
ensureOpen();
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
- jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
+ pos = zsrc.getEntryPos(zc.getBytesUTF8(entry.name), false);
} else {
- jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
+ pos = zsrc.getEntryPos(zc.getBytes(entry.name), false);
}
- if (jzentry == 0) {
+ if (pos == -1) {
return null;
}
- in = new ZipFileInputStream(jzentry);
-
- switch (getEntryMethod(jzentry)) {
+ in = new ZipFileInputStream(zsrc.cen, pos);
+ switch (CENHOW(zsrc.cen, pos)) {
case STORED:
synchronized (streams) {
streams.put(in, null);
}
return in;
case DEFLATED:
+ // Inflater likes a bit of slack
// MORE: Compute good size for inflater stream:
- long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
- if (size > 65536) size = 8192;
- if (size <= 0) size = 4096;
+ long size = CENLEN(zsrc.cen, pos) + 2;
+ if (size > 65536) {
+ size = 8192;
+ }
+ if (size <= 0) {
+ size = 4096;
+ }
Inflater inf = getInflater();
- InputStream is =
- new ZipFileInflaterInputStream(in, inf, (int)size);
+ InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size);
synchronized (streams) {
streams.put(is, inf);
}
@@ -386,7 +366,7 @@
}
private class ZipFileInflaterInputStream extends InflaterInputStream {
- private volatile boolean closeRequested = false;
+ private volatile boolean closeRequested;
private boolean eof = false;
private final ZipFileInputStream zfin;
@@ -447,8 +427,8 @@
private Inflater getInflater() {
Inflater inf;
synchronized (inflaterCache) {
- while (null != (inf = inflaterCache.poll())) {
- if (false == inf.ended()) {
+ while ((inf = inflaterCache.poll()) != null) {
+ if (!inf.ended()) {
return inf;
}
}
@@ -460,7 +440,7 @@
* Releases the specified inflater to the list of available inflaters.
*/
private void releaseInflater(Inflater inf) {
- if (false == inf.ended()) {
+ if (!inf.ended()) {
inf.reset();
synchronized (inflaterCache) {
inflaterCache.add(inf);
@@ -469,7 +449,7 @@
}
// List of available Inflater objects for decompression
- private Deque<Inflater> inflaterCache = new ArrayDeque<>();
+ private final Deque<Inflater> inflaterCache = new ArrayDeque<>();
/**
* Returns the path name of the ZIP file.
@@ -493,7 +473,7 @@
public boolean hasNext() {
synchronized (ZipFile.this) {
ensureOpen();
- return i < total;
+ return i < zsrc.total;
}
}
@@ -504,28 +484,11 @@
public ZipEntry next() {
synchronized (ZipFile.this) {
ensureOpen();
- if (i >= total) {
+ if (i >= zsrc.total) {
throw new NoSuchElementException();
}
- long jzentry = getNextEntry(jzfile, i++);
- if (jzentry == 0) {
- String message;
- if (closeRequested) {
- message = "ZipFile concurrently closed";
- } else {
- message = getZipMessage(ZipFile.this.jzfile);
- }
- throw new ZipError("jzentry == 0" +
- ",\n jzfile = " + ZipFile.this.jzfile +
- ",\n total = " + ZipFile.this.total +
- ",\n name = " + ZipFile.this.name +
- ",\n i = " + i +
- ",\n message = " + message
- );
- }
- ZipEntry ze = getZipEntry(null, jzentry);
- freeEntry(jzfile, jzentry);
- return ze;
+ // each "entry" has 3 ints in table entries
+ return getZipEntry(null, zsrc.getEntryPos(i++ * 3));
}
}
@@ -559,48 +522,53 @@
Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
}
- private ZipEntry getZipEntry(String name, long jzentry) {
+ /* Checks ensureOpen() before invoke this method */
+ private ZipEntry getZipEntry(String name, int pos) {
+ byte[] cen = zsrc.cen;
ZipEntry e = new ZipEntry();
- e.flag = getEntryFlag(jzentry); // get the flag first
+ int nlen = CENNAM(cen, pos);
+ int elen = CENEXT(cen, pos);
+ int clen = CENCOM(cen, pos);
+ e.flag = CENFLG(cen, pos); // get the flag first
if (name != null) {
e.name = name;
} else {
- byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
- e.name = zc.toStringUTF8(bname, bname.length);
+ e.name = zc.toStringUTF8(cen, pos + CENHDR, nlen);
} else {
- e.name = zc.toString(bname, bname.length);
+ e.name = zc.toString(cen, pos + CENHDR, nlen);
}
}
- e.xdostime = getEntryTime(jzentry);
- e.crc = getEntryCrc(jzentry);
- e.size = getEntrySize(jzentry);
- e.csize = getEntryCSize(jzentry);
- e.method = getEntryMethod(jzentry);
- e.setExtra0(getEntryBytes(jzentry, JZENTRY_EXTRA), false);
- byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
- if (bcomm == null) {
- e.comment = null;
- } else {
+ e.xdostime = CENTIM(cen, pos);
+ e.crc = CENCRC(cen, pos);
+ e.size = CENLEN(cen, pos);
+ e.csize = CENSIZ(cen, pos);
+ e.method = CENHOW(cen, pos);
+ if (elen != 0) {
+ e.setExtra0(Arrays.copyOfRange(cen, pos + CENHDR + nlen,
+ pos + CENHDR + nlen + elen), true);
+ }
+ if (clen != 0) {
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
- e.comment = zc.toStringUTF8(bcomm, bcomm.length);
+ e.comment = zc.toStringUTF8(cen, pos + CENHDR + nlen + elen, clen);
} else {
- e.comment = zc.toString(bcomm, bcomm.length);
+ e.comment = zc.toString(cen, pos + CENHDR + nlen + elen, clen);
}
}
return e;
}
- private static native long getNextEntry(long jzfile, int i);
-
/**
* Returns the number of entries in the ZIP file.
+ *
* @return the number of entries in the ZIP file
* @throws IllegalStateException if the zip file has been closed
*/
public int size() {
- ensureOpen();
- return total;
+ synchronized (this) {
+ ensureOpen();
+ return zsrc.total;
+ }
}
/**
@@ -612,14 +580,15 @@
* @throws IOException if an I/O error has occurred
*/
public void close() throws IOException {
- if (closeRequested)
+ if (closeRequested) {
return;
+ }
closeRequested = true;
synchronized (this) {
// Close streams, release their inflaters
synchronized (streams) {
- if (false == streams.isEmpty()) {
+ if (!streams.isEmpty()) {
Map<InputStream, Inflater> copy = new HashMap<>(streams);
streams.clear();
for (Map.Entry<InputStream, Inflater> e : copy.entrySet()) {
@@ -631,21 +600,17 @@
}
}
}
-
// Release cached inflaters
- Inflater inf;
synchronized (inflaterCache) {
- while (null != (inf = inflaterCache.poll())) {
+ Inflater inf;
+ while ((inf = inflaterCache.poll()) != null) {
inf.end();
}
}
-
- if (jzfile != 0) {
- // Close the zip file
- long zf = this.jzfile;
- jzfile = 0;
-
- close(zf);
+ // Release zip src
+ if (zsrc != null) {
+ Source.close(zsrc);
+ zsrc = null;
}
}
}
@@ -668,14 +633,11 @@
close();
}
- private static native void close(long jzfile);
-
private void ensureOpen() {
if (closeRequested) {
throw new IllegalStateException("zip file closed");
}
-
- if (jzfile == 0) {
+ if (zsrc == null) {
throw new IllegalStateException("The object is not initialized.");
}
}
@@ -691,40 +653,99 @@
* (possibly compressed) zip file entry.
*/
private class ZipFileInputStream extends InputStream {
- private volatile boolean zfisCloseRequested = false;
- protected long jzentry; // address of jzentry data
+ private volatile boolean closeRequested;
private long pos; // current position within entry data
protected long rem; // number of remaining bytes within entry
protected long size; // uncompressed size of this entry
- ZipFileInputStream(long jzentry) {
- pos = 0;
- rem = getEntryCSize(jzentry);
- size = getEntrySize(jzentry);
- this.jzentry = jzentry;
+ ZipFileInputStream(byte[] cen, int cenpos) throws IOException {
+ rem = CENSIZ(cen, cenpos);
+ size = CENLEN(cen, cenpos);
+ pos = CENOFF(cen, cenpos);
+ // zip64
+ if (rem == ZIP64_MAGICVAL || size == ZIP64_MAGICVAL ||
+ pos == ZIP64_MAGICVAL) {
+ checkZIP64(cen, cenpos);
+ }
+ // negative for lazy initialization, see getDataOffset();
+ pos = - (pos + ZipFile.this.zsrc.locpos);
+ }
+
+ private void checkZIP64(byte[] cen, int cenpos) throws IOException {
+ int off = cenpos + CENHDR + CENNAM(cen, cenpos);
+ int end = off + CENEXT(cen, cenpos);
+ while (off + 4 < end) {
+ int tag = get16(cen, off);
+ int sz = get16(cen, off + 2);
+ off += 4;
+ if (off + sz > end) // invalid data
+ break;
+ if (tag == EXTID_ZIP64) {
+ if (size == ZIP64_MAGICVAL) {
+ if (sz < 8 || (off + 8) > end)
+ break;
+ size = get64(cen, off);
+ sz -= 8;
+ off += 8;
+ }
+ if (rem == ZIP64_MAGICVAL) {
+ if (sz < 8 || (off + 8) > end)
+ break;
+ rem = get64(cen, off);
+ sz -= 8;
+ off += 8;
+ }
+ if (pos == ZIP64_MAGICVAL) {
+ if (sz < 8 || (off + 8) > end)
+ break;
+ pos = get64(cen, off);
+ sz -= 8;
+ off += 8;
+ }
+ break;
+ }
+ off += sz;
+ }
+ }
+
+ /* The Zip file spec explicitly allows the LOC extra data size to
+ * be different from the CEN extra data size. Since we cannot trust
+ * the CEN extra data size, we need to read the LOC to determine
+ * the entry data offset.
+ */
+ private long initDataOffset() throws IOException {
+ if (pos <= 0) {
+ byte[] loc = new byte[LOCHDR];
+ pos = -pos;
+ int len = ZipFile.this.zsrc.readFullyAt(loc, 0, loc.length, pos);
+ if (len != LOCHDR) {
+ throw new ZipException("ZipFile error reading zip file");
+ }
+ if (LOCSIG(loc) != LOCSIG) {
+ throw new ZipException("ZipFile invalid LOC header (bad signature)");
+ }
+ pos += LOCHDR + LOCNAM(loc) + LOCEXT(loc);
+ }
+ return pos;
}
public int read(byte b[], int off, int len) throws IOException {
synchronized (ZipFile.this) {
- long rem = this.rem;
- long pos = this.pos;
+ ensureOpenOrZipException();
+ initDataOffset();
if (rem == 0) {
return -1;
}
+ if (len > rem) {
+ len = (int) rem;
+ }
if (len <= 0) {
return 0;
}
- if (len > rem) {
- len = (int) rem;
- }
-
- // Check if ZipFile open
- ensureOpenOrZipException();
- len = ZipFile.read(ZipFile.this.jzfile, jzentry, pos, b,
- off, len);
+ len = ZipFile.this.zsrc.readAt(b, off, len, pos);
if (len > 0) {
- this.pos = (pos + len);
- this.rem = (rem - len);
+ pos += len;
+ rem -= len;
}
}
if (rem == 0) {
@@ -742,11 +763,16 @@
}
}
- public long skip(long n) {
- if (n > rem)
- n = rem;
- pos += n;
- rem -= n;
+ public long skip(long n) throws IOException {
+ synchronized (ZipFile.this) {
+ ensureOpenOrZipException();
+ initDataOffset();
+ if (n > rem) {
+ n = rem;
+ }
+ pos += n;
+ rem -= n;
+ }
if (rem == 0) {
close();
}
@@ -762,17 +788,11 @@
}
public void close() {
- if (zfisCloseRequested)
+ if (closeRequested) {
return;
- zfisCloseRequested = true;
-
+ }
+ closeRequested = true;
rem = 0;
- synchronized (ZipFile.this) {
- if (jzentry != 0 && ZipFile.this.jzfile != 0) {
- freeEntry(ZipFile.this.jzfile, jzentry);
- jzentry = 0;
- }
- }
synchronized (streams) {
streams.remove(this);
}
@@ -787,40 +807,502 @@
SharedSecrets.setJavaUtilZipFileAccess(
new JavaUtilZipFileAccess() {
public boolean startsWithLocHeader(ZipFile zip) {
- return zip.startsWithLocHeader();
+ return zip.zsrc.startsWithLoc;
}
- }
+ public String[] getMetaInfEntryNames(ZipFile zip) {
+ return zip.getMetaInfEntryNames();
+ }
+ }
);
}
- /**
- * Returns {@code true} if, and only if, the zip file begins with {@code
- * LOCSIG}.
+ /*
+ * Returns an array of strings representing the names of all entries
+ * that begin with "META-INF/" (case ignored). This method is used
+ * in JarFile, via SharedSecrets, as an optimization when looking up
+ * manifest and signature file entries. Returns null if no entries
+ * were found.
*/
- private boolean startsWithLocHeader() {
- return locsig;
+ private String[] getMetaInfEntryNames() {
+ synchronized (this) {
+ ensureOpen();
+ if (zsrc.metanames.size() == 0) {
+ return null;
+ }
+ String[] names = new String[zsrc.metanames.size()];
+ byte[] cen = zsrc.cen;
+ for (int i = 0; i < names.length; i++) {
+ int pos = zsrc.metanames.get(i);
+ names[i] = new String(cen, pos + CENHDR, CENNAM(cen, pos),
+ StandardCharsets.UTF_8);
+ }
+ return names;
+ }
}
- private static native long open(String name, int mode, long lastModified,
- boolean usemmap) throws IOException;
- private static native int getTotal(long jzfile);
- private static native boolean startsWithLOC(long jzfile);
- private static native int read(long jzfile, long jzentry,
- long pos, byte[] b, int off, int len);
+ private static class Source {
+ private final Key key; // the key in files
+ private int refs = 1;
+
+ private RandomAccessFile zfile; // zfile of the underlying zip file
+ private byte[] cen; // CEN & ENDHDR
+ private long locpos; // position of first LOC header (usually 0)
+ private byte[] comment; // zip file comment
+ // list of meta entries in META-INF dir
+ private ArrayList<Integer> metanames = new ArrayList<>();
+ private final boolean startsWithLoc; // true, if zip file starts with LOCSIG (usually true)
+
+ // A Hashmap for all entries.
+ //
+ // A cen entry of Zip/JAR file. As we have one for every entry in every active Zip/JAR,
+ // We might have a lot of these in a typical system. In order to save space we don't
+ // keep the name in memory, but merely remember a 32 bit {@code hash} value of the
+ // entry name and its offset {@code pos} in the central directory hdeader.
+ //
+ // private static class Entry {
+ // int hash; // 32 bit hashcode on name
+ // int next; // hash chain: index into entries
+ // int pos; // Offset of central directory file header
+ // }
+ // private Entry[] entries; // array of hashed cen entry
+ //
+ // To reduce the total size of entries further, we use a int[] here to store 3 "int"
+ // {@code hash}, {@code next and {@code "pos for each entry. The entry can then be
+ // referred by their index of their positions in the {@code entries}.
+ //
+ private int[] entries; // array of hashed cen entry
+ private int addEntry(int index, int hash, int next, int pos) {
+ entries[index++] = hash;
+ entries[index++] = next;
+ entries[index++] = pos;
+ return index;
+ }
+ private int getEntryHash(int index) { return entries[index]; }
+ private int getEntryNext(int index) { return entries[index + 1]; }
+ private int getEntryPos(int index) { return entries[index + 2]; }
+ private static final int ZIP_ENDCHAIN = -1;
+ private int total; // total number of entries
+ private int[] table; // Hash chain heads: indexes into entries
+ private int tablelen; // number of hash heads
+
+ private static class Key {
+ BasicFileAttributes attrs;
+ File file;
+
+ public Key(File file, BasicFileAttributes attrs) {
+ this.attrs = attrs;
+ this.file = file;
+ }
+
+ public int hashCode() {
+ long t = attrs.lastModifiedTime().toMillis();
+ return ((int)(t ^ (t >>> 32))) + file.hashCode();
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof Key) {
+ Key key = (Key)obj;
+ if (!attrs.lastModifiedTime().equals(key.attrs.lastModifiedTime())) {
+ return false;
+ }
+ Object fk = attrs.fileKey();
+ if (fk != null) {
+ return fk.equals(key.attrs.fileKey());
+ } else {
+ return file.equals(key.file);
+ }
+ }
+ return false;
+ }
+ }
+ private static final HashMap<Key, Source> files = new HashMap<>();
+
+
+ public static Source get(File file, boolean toDelete) throws IOException {
+ Key key = new Key(file,
+ Files.readAttributes(file.toPath(), BasicFileAttributes.class));
+ Source src = null;
+ synchronized (files) {
+ src = files.get(key);
+ if (src != null) {
+ src.refs++;
+ return src;
+ }
+ }
+ src = new Source(key, toDelete);
+
+ synchronized (files) {
+ if (files.containsKey(key)) { // someone else put in first
+ src.close(); // close the newly created one
+ src = files.get(key);
+ src.refs++;
+ return src;
+ }
+ files.put(key, src);
+ return src;
+ }
+ }
+
+ private static void close(Source src) throws IOException {
+ synchronized (files) {
+ if (--src.refs == 0) {
+ files.remove(src.key);
+ src.close();
+ }
+ }
+ }
+
+ private Source(Key key, boolean toDelete) throws IOException {
+ this.key = key;
+ this.zfile = new RandomAccessFile(key.file, "r");
+ if (toDelete) {
+ key.file.delete();
+ }
+ try {
+ initCEN(-1);
+ byte[] buf = new byte[4];
+ readFullyAt(buf, 0, 4, 0);
+ this.startsWithLoc = (LOCSIG(buf) == LOCSIG);
+ } catch (IOException x) {
+ try {
+ this.zfile.close();
+ } catch (IOException xx) {}
+ throw x;
+ }
+ }
+
+ private void close() throws IOException {
+ zfile.close();
+ zfile = null;
+ cen = null;
+ entries = null;
+ table = null;
+ metanames = null;
+ }
+
+ private static final int BUF_SIZE = 8192;
+ private final int readFullyAt(byte[] buf, int off, int len, long pos)
+ throws IOException
+ {
+ synchronized(zfile) {
+ zfile.seek(pos);
+ int N = len;
+ while (N > 0) {
+ int n = Math.min(BUF_SIZE, N);
+ zfile.readFully(buf, off, n);
+ off += n;
+ N -= n;
+ }
+ return len;
+ }
+ }
+
+ private final int readAt(byte[] buf, int off, int len, long pos)
+ throws IOException
+ {
+ synchronized(zfile) {
+ zfile.seek(pos);
+ return zfile.read(buf, off, len);
+ }
+ }
+
+ private static final int hashN(byte[] a, int off, int len) {
+ int h = 1;
+ while (len-- > 0) {
+ h = 31 * h + a[off++];
+ }
+ return h;
+ }
+
+ private static final int hash_append(int hash, byte b) {
+ return hash * 31 + b;
+ }
+
+ private static class End {
+ int centot; // 4 bytes
+ long cenlen; // 4 bytes
+ long cenoff; // 4 bytes
+ long endpos; // 4 bytes
+ }
- // access to the native zentry object
- private static native long getEntryTime(long jzentry);
- private static native long getEntryCrc(long jzentry);
- private static native long getEntryCSize(long jzentry);
- private static native long getEntrySize(long jzentry);
- private static native int getEntryMethod(long jzentry);
- private static native int getEntryFlag(long jzentry);
- private static native byte[] getCommentBytes(long jzfile);
+ /*
+ * Searches for end of central directory (END) header. The contents of
+ * the END header will be read and placed in endbuf. Returns the file
+ * position of the END header, otherwise returns -1 if the END header
+ * was not found or an error occurred.
+ */
+ private End findEND() throws IOException {
+ long ziplen = zfile.length();
+ if (ziplen <= 0)
+ zerror("zip file is empty");
+ End end = new End();
+ byte[] buf = new byte[READBLOCKSZ];
+ long minHDR = (ziplen - END_MAXLEN) > 0 ? ziplen - END_MAXLEN : 0;
+ long minPos = minHDR - (buf.length - ENDHDR);
+ for (long pos = ziplen - buf.length; pos >= minPos; pos -= (buf.length - ENDHDR)) {
+ int off = 0;
+ if (pos < 0) {
+ // Pretend there are some NUL bytes before start of file
+ off = (int)-pos;
+ Arrays.fill(buf, 0, off, (byte)0);
+ }
+ int len = buf.length - off;
+ if (readFullyAt(buf, off, len, pos + off) != len ) {
+ zerror("zip END header not found");
+ }
+ // Now scan the block backwards for END header signature
+ for (int i = buf.length - ENDHDR; i >= 0; i--) {
+ if (buf[i+0] == (byte)'P' &&
+ buf[i+1] == (byte)'K' &&
+ buf[i+2] == (byte)'\005' &&
+ buf[i+3] == (byte)'\006') {
+ // Found ENDSIG header
+ byte[] endbuf = Arrays.copyOfRange(buf, i, i + ENDHDR);
+ end.centot = ENDTOT(endbuf);
+ end.cenlen = ENDSIZ(endbuf);
+ end.cenoff = ENDOFF(endbuf);
+ end.endpos = pos + i;
+ int comlen = ENDCOM(endbuf);
+ if (end.endpos + ENDHDR + comlen != ziplen) {
+ // ENDSIG matched, however the size of file comment in it does
+ // not match the real size. One "common" cause for this problem
+ // is some "extra" bytes are padded at the end of the zipfile.
+ // Let's do some extra verification, we don't care about the
+ // performance in this situation.
+ byte[] sbuf = new byte[4];
+ long cenpos = end.endpos - end.cenlen;
+ long locpos = cenpos - end.cenoff;
+ if (cenpos < 0 ||
+ locpos < 0 ||
+ readFullyAt(sbuf, 0, sbuf.length, cenpos) != 4 ||
+ GETSIG(sbuf) != CENSIG ||
+ readFullyAt(sbuf, 0, sbuf.length, locpos) != 4 ||
+ GETSIG(sbuf) != LOCSIG) {
+ continue;
+ }
+ }
+ if (comlen > 0) { // this zip file has comlen
+ comment = new byte[comlen];
+ if (readFullyAt(comment, 0, comlen, end.endpos + ENDHDR) != comlen) {
+ zerror("zip comment read failed");
+ }
+ }
+ if (end.cenlen == ZIP64_MAGICVAL ||
+ end.cenoff == ZIP64_MAGICVAL ||
+ end.centot == ZIP64_MAGICCOUNT)
+ {
+ // need to find the zip64 end;
+ try {
+ byte[] loc64 = new byte[ZIP64_LOCHDR];
+ if (readFullyAt(loc64, 0, loc64.length, end.endpos - ZIP64_LOCHDR)
+ != loc64.length || GETSIG(loc64) != ZIP64_LOCSIG) {
+ return end;
+ }
+ long end64pos = ZIP64_LOCOFF(loc64);
+ byte[] end64buf = new byte[ZIP64_ENDHDR];
+ if (readFullyAt(end64buf, 0, end64buf.length, end64pos)
+ != end64buf.length || GETSIG(end64buf) != ZIP64_ENDSIG) {
+ return end;
+ }
+ // end64 found, re-calcualte everything.
+ end.cenlen = ZIP64_ENDSIZ(end64buf);
+ end.cenoff = ZIP64_ENDOFF(end64buf);
+ end.centot = (int)ZIP64_ENDTOT(end64buf); // assume total < 2g
+ end.endpos = end64pos;
+ } catch (IOException x) {} // no zip64 loc/end
+ }
+ return end;
+ }
+ }
+ }
+ zerror("zip END header not found");
+ return null; //make compiler happy
+ }
+
+ // Reads zip file central directory.
+ private void initCEN(int knownTotal) throws IOException {
+ if (knownTotal == -1) {
+ End end = findEND();
+ if (end.endpos == 0) {
+ locpos = 0;
+ total = 0;
+ entries = new int[0];
+ cen = null;
+ return; // only END header present
+ }
+ if (end.cenlen > end.endpos)
+ zerror("invalid END header (bad central directory size)");
+ long cenpos = end.endpos - end.cenlen; // position of CEN table
+ // Get position of first local file (LOC) header, taking into
+ // account that there may be a stub prefixed to the zip file.
+ locpos = cenpos - end.cenoff;
+ if (locpos < 0) {
+ zerror("invalid END header (bad central directory offset)");
+ }
+ // read in the CEN and END
+ cen = new byte[(int)(end.cenlen + ENDHDR)];
+ if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) {
+ zerror("read CEN tables failed");
+ }
+ total = end.centot;
+ } else {
+ total = knownTotal;
+ }
+ // hash table for entries
+ entries = new int[total * 3];
+ tablelen = ((total/2) | 1); // Odd -> fewer collisions
+ table = new int[tablelen];
+ Arrays.fill(table, ZIP_ENDCHAIN);
+ int idx = 0;
+ int hash = 0;
+ int next = -1;
+
+ // list for all meta entries
+ metanames = new ArrayList<>();
- private static final int JZENTRY_NAME = 0;
- private static final int JZENTRY_EXTRA = 1;
- private static final int JZENTRY_COMMENT = 2;
- private static native byte[] getEntryBytes(long jzentry, int type);
+ // Iterate through the entries in the central directory
+ int i = 0;
+ int hsh = 0;
+ int pos = 0;
+ int limit = cen.length - ENDHDR;
+ while (pos + CENHDR <= limit) {
+ if (i >= total) {
+ // This will only happen if the zip file has an incorrect
+ // ENDTOT field, which usually means it contains more than
+ // 65535 entries.
+ initCEN(countCENHeaders(cen, limit));
+ return;
+ }
+ if (CENSIG(cen, pos) != CENSIG)
+ zerror("invalid CEN header (bad signature)");
+ int method = CENHOW(cen, pos);
+ int nlen = CENNAM(cen, pos);
+ int elen = CENEXT(cen, pos);
+ int clen = CENCOM(cen, pos);
+ if ((CENFLG(cen, pos) & 1) != 0)
+ zerror("invalid CEN header (encrypted entry)");
+ if (method != STORED && method != DEFLATED)
+ zerror("invalid CEN header (bad compression method: " + method + ")");
+ if (pos + CENHDR + nlen > limit)
+ zerror("invalid CEN header (bad header size)");
+ // Record the CEN offset and the name hash in our hash cell.
+ hash = hashN(cen, pos + CENHDR, nlen);
+ hsh = (hash & 0x7fffffff) % tablelen;
+ next = table[hsh];
+ table[hsh] = idx;
+ idx = addEntry(idx, hash, next, pos);
+ // Adds name to metanames.
+ if (isMetaName(cen, pos + CENHDR, nlen)) {
+ metanames.add(pos);
+ }
+ // skip ext and comment
+ pos += (CENHDR + nlen + elen + clen);
+ i++;
+ }
+ total = i;
+ if (pos + ENDHDR != cen.length) {
+ zerror("invalid CEN header (bad header size)");
+ }
+ }
+
+ private static void zerror(String msg) throws ZipException {
+ throw new ZipException(msg);
+ }
- private static native String getZipMessage(long jzfile);
+ /*
+ * Returns the {@code pos} of the zip cen entry corresponding to the
+ * specified entry name, or -1 if not found.
+ */
+ private int getEntryPos(byte[] name, boolean addSlash) {
+ if (total == 0) {
+ return -1;
+ }
+ int hsh = hashN(name, 0, name.length);
+ int idx = table[(hsh & 0x7fffffff) % tablelen];
+ /*
+ * This while loop is an optimization where a double lookup
+ * for name and name+/ is being performed. The name char
+ * array has enough room at the end to try again with a
+ * slash appended if the first table lookup does not succeed.
+ */
+ while(true) {
+ /*
+ * Search down the target hash chain for a entry whose
+ * 32 bit hash matches the hashed name.
+ */
+ while (idx != ZIP_ENDCHAIN) {
+ if (getEntryHash(idx) == hsh) {
+ // The CEN name must match the specfied one
+ int pos = getEntryPos(idx);
+ if (name.length == CENNAM(cen, pos)) {
+ boolean matched = true;
+ int nameoff = pos + CENHDR;
+ for (int i = 0; i < name.length; i++) {
+ if (name[i] != cen[nameoff++]) {
+ matched = false;
+ break;
+ }
+ }
+ if (matched) {
+ return pos;
+ }
+ }
+ }
+ idx = getEntryNext(idx);
+ }
+ /* If not addSlash, or slash is already there, we are done */
+ if (!addSlash || name[name.length - 1] == '/') {
+ return -1;
+ }
+ /* Add slash and try once more */
+ name = Arrays.copyOf(name, name.length + 1);
+ name[name.length - 1] = '/';
+ hsh = hash_append(hsh, (byte)'/');
+ //idx = table[hsh % tablelen];
+ idx = table[(hsh & 0x7fffffff) % tablelen];
+ addSlash = false;
+ }
+ }
+
+ private static byte[] metainf = new byte[] {
+ 'M', 'E', 'T', 'A', '-', 'I' , 'N', 'F', '/',
+ };
+
+ /*
+ * Returns true if the specified entry's name begins with the string
+ * "META-INF/" irrespective of case.
+ */
+ private static boolean isMetaName(byte[] name, int off, int len) {
+ if (len < 9 || (name[off] != 'M' && name[off] != 'm')) { // sizeof("META-INF/") - 1
+ return false;
+ }
+ off++;
+ for (int i = 1; i < metainf.length; i++) {
+ byte c = name[off++];
+ // Avoid toupper; it's locale-dependent
+ if (c >= 'a' && c <= 'z') {
+ c += 'A' - 'a';
+ }
+ if (metainf[i] != c) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Counts the number of CEN headers in a central directory extending
+ * from BEG to END. Might return a bogus answer if the zip file is
+ * corrupt, but will not crash.
+ */
+ static int countCENHeaders(byte[] cen, int end) {
+ int count = 0;
+ int pos = 0;
+ while (pos + CENHDR <= end) {
+ count++;
+ pos += (CENHDR + CENNAM(cen, pos) + CENEXT(cen, pos) + CENCOM(cen, pos));
+ }
+ return count;
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/java/util/zip/ZipUtils.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,6 +31,8 @@
import java.time.ZoneId;
import java.util.concurrent.TimeUnit;
+import static java.util.zip.ZipConstants.ENDHDR;
+
class ZipUtils {
// used to adjust values between Windows and java epoch
@@ -133,7 +135,7 @@
* The bytes are assumed to be in Intel (little-endian) byte order.
*/
public static final int get16(byte b[], int off) {
- return Byte.toUnsignedInt(b[off]) | (Byte.toUnsignedInt(b[off+1]) << 8);
+ return (b[off] & 0xff) | ((b[off + 1] & 0xff) << 8);
}
/**
@@ -160,4 +162,79 @@
public static final int get32S(byte b[], int off) {
return (get16(b, off) | (get16(b, off+2) << 16));
}
+
+ // fields access methods
+ static final int CH(byte[] b, int n) {
+ return b[n] & 0xff ;
+ }
+
+ static final int SH(byte[] b, int n) {
+ return (b[n] & 0xff) | ((b[n + 1] & 0xff) << 8);
+ }
+
+ static final long LG(byte[] b, int n) {
+ return ((SH(b, n)) | (SH(b, n + 2) << 16)) & 0xffffffffL;
+ }
+
+ static final long LL(byte[] b, int n) {
+ return (LG(b, n)) | (LG(b, n + 4) << 32);
+ }
+
+ static final long GETSIG(byte[] b) {
+ return LG(b, 0);
+ }
+
+ // local file (LOC) header fields
+ static final long LOCSIG(byte[] b) { return LG(b, 0); } // signature
+ static final int LOCVER(byte[] b) { return SH(b, 4); } // version needed to extract
+ static final int LOCFLG(byte[] b) { return SH(b, 6); } // general purpose bit flags
+ static final int LOCHOW(byte[] b) { return SH(b, 8); } // compression method
+ static final long LOCTIM(byte[] b) { return LG(b, 10);} // modification time
+ static final long LOCCRC(byte[] b) { return LG(b, 14);} // crc of uncompressed data
+ static final long LOCSIZ(byte[] b) { return LG(b, 18);} // compressed data size
+ static final long LOCLEN(byte[] b) { return LG(b, 22);} // uncompressed data size
+ static final int LOCNAM(byte[] b) { return SH(b, 26);} // filename length
+ static final int LOCEXT(byte[] b) { return SH(b, 28);} // extra field length
+
+ // extra local (EXT) header fields
+ static final long EXTCRC(byte[] b) { return LG(b, 4);} // crc of uncompressed data
+ static final long EXTSIZ(byte[] b) { return LG(b, 8);} // compressed size
+ static final long EXTLEN(byte[] b) { return LG(b, 12);} // uncompressed size
+
+ // end of central directory header (END) fields
+ static final int ENDSUB(byte[] b) { return SH(b, 8); } // number of entries on this disk
+ static final int ENDTOT(byte[] b) { return SH(b, 10);} // total number of entries
+ static final long ENDSIZ(byte[] b) { return LG(b, 12);} // central directory size
+ static final long ENDOFF(byte[] b) { return LG(b, 16);} // central directory offset
+ static final int ENDCOM(byte[] b) { return SH(b, 20);} // size of zip file comment
+ static final int ENDCOM(byte[] b, int off) { return SH(b, off + 20);}
+
+ // zip64 end of central directory recoder fields
+ static final long ZIP64_ENDTOD(byte[] b) { return LL(b, 24);} // total number of entries on disk
+ static final long ZIP64_ENDTOT(byte[] b) { return LL(b, 32);} // total number of entries
+ static final long ZIP64_ENDSIZ(byte[] b) { return LL(b, 40);} // central directory size
+ static final long ZIP64_ENDOFF(byte[] b) { return LL(b, 48);} // central directory offset
+ static final long ZIP64_LOCOFF(byte[] b) { return LL(b, 8);} // zip64 end offset
+
+ // central directory header (CEN) fields
+ static final long CENSIG(byte[] b, int pos) { return LG(b, pos + 0); }
+ static final int CENVEM(byte[] b, int pos) { return SH(b, pos + 4); }
+ static final int CENVER(byte[] b, int pos) { return SH(b, pos + 6); }
+ static final int CENFLG(byte[] b, int pos) { return SH(b, pos + 8); }
+ static final int CENHOW(byte[] b, int pos) { return SH(b, pos + 10);}
+ static final long CENTIM(byte[] b, int pos) { return LG(b, pos + 12);}
+ static final long CENCRC(byte[] b, int pos) { return LG(b, pos + 16);}
+ static final long CENSIZ(byte[] b, int pos) { return LG(b, pos + 20);}
+ static final long CENLEN(byte[] b, int pos) { return LG(b, pos + 24);}
+ static final int CENNAM(byte[] b, int pos) { return SH(b, pos + 28);}
+ static final int CENEXT(byte[] b, int pos) { return SH(b, pos + 30);}
+ static final int CENCOM(byte[] b, int pos) { return SH(b, pos + 32);}
+ static final int CENDSK(byte[] b, int pos) { return SH(b, pos + 34);}
+ static final int CENATT(byte[] b, int pos) { return SH(b, pos + 36);}
+ static final long CENATX(byte[] b, int pos) { return LG(b, pos + 38);}
+ static final long CENOFF(byte[] b, int pos) { return LG(b, pos + 42);}
+
+ // The END header is followed by a variable length comment of size < 64k.
+ static final long END_MAXLEN = 0xFFFF + ENDHDR;
+ static final int READBLOCKSZ = 128;
}
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java Wed Jan 06 14:54:24 2016 +0000
@@ -326,20 +326,22 @@
}
// Do not expose this outside of this package.
- private static volatile LoggerFinder provider = null;
+ private static volatile LoggerFinder provider;
private static LoggerFinder accessLoggerFinder() {
- if (provider == null) {
+ LoggerFinder prov = provider;
+ if (prov == null) {
// no need to lock: it doesn't matter if we call
// getLoggerFinder() twice - since LoggerFinder already caches
// the result.
// This is just an optimization to avoid the cost of calling
// doPrivileged every time.
final SecurityManager sm = System.getSecurityManager();
- provider = sm == null ? LoggerFinder.getLoggerFinder() :
+ prov = sm == null ? LoggerFinder.getLoggerFinder() :
AccessController.doPrivileged(
(PrivilegedAction<LoggerFinder>)LoggerFinder::getLoggerFinder);
+ provider = prov;
}
- return provider;
+ return prov;
}
// Avoid using lambda here as lazy loggers could be created early
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,6 +28,7 @@
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.StackWalker.StackFrame;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.time.ZonedDateTime;
@@ -180,7 +181,16 @@
* CallerFinder is a stateful predicate.
*/
static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
- static final StackWalker WALKER = StackWalker.getInstance();
+ private static final StackWalker WALKER;
+ static {
+ final PrivilegedAction<StackWalker> action = new PrivilegedAction<>() {
+ @Override
+ public StackWalker run() {
+ return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ }
+ };
+ WALKER = AccessController.doPrivileged(action);
+ }
/**
* Returns StackFrame of the caller's frame.
@@ -210,8 +220,9 @@
lookingForLogger = !isLoggerImplFrame(cname);
return false;
}
- // We've found the relevant frame.
- return !skipLoggingFrame(cname) && !isLoggerImplFrame(cname);
+ // Continue walking until we've found the relevant calling frame.
+ // Skips logging/logger infrastructure.
+ return !isFilteredFrame(t);
}
private boolean isLoggerImplFrame(String cname) {
@@ -281,8 +292,8 @@
return Formatting.getSimpleFormat(defaultPropertyGetter);
}
- public static boolean skipLoggingFrame(String cname) {
- return Formatting.skipLoggingFrame(cname);
+ public static boolean isFilteredFrame(StackFrame st) {
+ return Formatting.isFilteredFrame(st);
}
@Override
@@ -393,16 +404,19 @@
}
- static boolean skipLoggingFrame(String cname) {
+ static boolean isFilteredFrame(StackFrame st) {
// skip logging/logger infrastructure
+ if (System.Logger.class.isAssignableFrom(st.getDeclaringClass())) {
+ return true;
+ }
// fast escape path: all the prefixes below start with 's' or 'j' and
// have more than 12 characters.
+ final String cname = st.getClassName();
char c = cname.length() < 12 ? 0 : cname.charAt(0);
if (c == 's') {
// skip internal machinery classes
if (cname.startsWith("sun.util.logging.")) return true;
- if (cname.startsWith("sun.reflect.")) return true;
if (cname.startsWith("sun.rmi.runtime.Log")) return true;
} else if (c == 'j') {
// Message delayed at Bootstrap: no need to go further up.
@@ -410,10 +424,7 @@
// skip public machinery classes
if (cname.startsWith("jdk.internal.logger.")) return true;
if (cname.startsWith("java.util.logging.")) return true;
- if (cname.startsWith("java.lang.System$Logger")) return true;
- if (cname.startsWith("java.lang.reflect.")) return true;
if (cname.startsWith("java.lang.invoke.MethodHandle")) return true;
- if (cname.startsWith("java.lang.invoke.LambdaForm")) return true;
if (cname.startsWith("java.security.AccessController")) return true;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 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. 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.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>double</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class DoubleConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private DoubleConsts() {}
+
+ public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
+ public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
+ public static final double NaN = java.lang.Double.NaN;
+ public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
+ public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>double</code>, 2<sup>-1022</sup>. It is equal to the
+ * value returned by
+ * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
+ *
+ * @since 1.5
+ */
+ public static final double MIN_NORMAL = 2.2250738585072014E-308;
+
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>double</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 53;
+
+ /**
+ * Maximum exponent a finite <code>double</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Double.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 1023;
+
+ /**
+ * Minimum exponent a normalized <code>double</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -1022;
+
+ /**
+ * The exponent the smallest positive <code>double</code>
+ * subnormal value would have if it could be normalized..
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>double</code> exponent.
+ */
+ public static final int EXP_BIAS = 1023;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>double</code>.
+ */
+ public static final long SIGN_BIT_MASK = 0x8000000000000000L;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>double</code>.
+ */
+ public static final long EXP_BIT_MASK = 0x7FF0000000000000L;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>double</code>.
+ */
+ public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.math;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+ //
+ // This class contains many comments that start with "/*@" mark.
+ // They are behavourial specification in
+ // the Java Modelling Language (JML):
+ // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+ //
+
+ /*@
+ @ public pure model static \bigint UNSIGNED(int v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 32);
+ @ }
+ @
+ @ public pure model static \bigint UNSIGNED(long v) {
+ @ return v >= 0 ? v : v + (((\bigint)1) << 64);
+ @ }
+ @
+ @ public pure model static \bigint AP(int[] data, int len) {
+ @ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+ @ }
+ @
+ @ public pure model static \bigint pow52(int p5, int p2) {
+ @ ghost \bigint v = 1;
+ @ for (int i = 0; i < p5; i++) v *= 5;
+ @ return v << p2;
+ @ }
+ @
+ @ public pure model static \bigint pow10(int p10) {
+ @ return pow52(p10, p10);
+ @ }
+ @*/
+
+ static final int[] SMALL_5_POW = {
+ 1,
+ 5,
+ 5 * 5,
+ 5 * 5 * 5,
+ 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+ };
+
+ static final long[] LONG_5_POW = {
+ 1L,
+ 5L,
+ 5L * 5,
+ 5L * 5 * 5,
+ 5L * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+ };
+
+ // Maximum size of cache of powers of 5 as FDBigIntegers.
+ private static final int MAX_FIVE_POW = 340;
+
+ // Cache of big powers of 5 as FDBigIntegers.
+ private static final FDBigInteger POW_5_CACHE[];
+
+ // Initialize FDBigInteger cache of powers of 5.
+ static {
+ POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+ int i = 0;
+ while (i < SMALL_5_POW.length) {
+ FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+ pow5.makeImmutable();
+ POW_5_CACHE[i] = pow5;
+ i++;
+ }
+ FDBigInteger prev = POW_5_CACHE[i - 1];
+ while (i < MAX_FIVE_POW) {
+ POW_5_CACHE[i] = prev = prev.mult(5);
+ prev.makeImmutable();
+ i++;
+ }
+ }
+
+ // Zero as an FDBigInteger.
+ public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+ // Ensure ZERO is immutable.
+ static {
+ ZERO.makeImmutable();
+ }
+
+ // Constant for casting an int to a long via bitwise AND.
+ private static final long LONG_MASK = 0xffffffffL;
+
+ //@ spec_public non_null;
+ private int data[]; // value: data[0] is least significant
+ //@ spec_public;
+ private int offset; // number of least significant zero padding ints
+ //@ spec_public;
+ private int nWords; // data[nWords-1]!=0, all values above are zero
+ // if nWords==0 -> this FDBigInteger is zero
+ //@ spec_public;
+ private boolean isImmutable = false;
+
+ /*@
+ @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ public invariant nWords == 0 ==> offset == 0;
+ @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+ @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+ @ public pure model \bigint value() {
+ @ return AP(data, nWords) << (offset*32);
+ @ }
+ @*/
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from data and padding. The
+ * <code>data</code> parameter has the least significant <code>int</code> at
+ * the zeroth index. The <code>offset</code> parameter gives the number of
+ * zero <code>int</code>s to be inferred below the least significant element
+ * of <code>data</code>.
+ *
+ * @param data An array containing all non-zero <code>int</code>s of the value.
+ * @param offset An offset indicating the number of zero <code>int</code>s to pad
+ * below the least significant element of <code>data</code>.
+ */
+ /*@
+ @ requires data != null && offset >= 0;
+ @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+ @ ensures this.data == \old(data);
+ @*/
+ private FDBigInteger(int[] data, int offset) {
+ this.data = data;
+ this.offset = offset;
+ this.nWords = data.length;
+ trimLeadingZeros();
+ }
+
+ /**
+ * Constructs an <code>FDBigInteger</code> from a starting value and some
+ * decimal digits.
+ *
+ * @param lValue The starting value.
+ * @param digits The decimal digits.
+ * @param kDigits The initial index into <code>digits</code>.
+ * @param nDigits The final index into <code>digits</code>.
+ */
+ /*@
+ @ requires digits != null;
+ @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+ @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+ @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+ @*/
+ public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+ int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
+ data = new int[n]; // allocate enough space
+ data[0] = (int) lValue; // starting value
+ data[1] = (int) (lValue >>> 32);
+ offset = 0;
+ nWords = 2;
+ int i = kDigits;
+ int limit = nDigits - 5; // slurp digits 5 at a time.
+ int v;
+ while (i < limit) {
+ int ilim = i + 5;
+ v = (int) digits[i++] - (int) '0';
+ while (i < ilim) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ }
+ multAddMe(100000, v); // ... where 100000 is 10^5.
+ }
+ int factor = 1;
+ v = 0;
+ while (i < nDigits) {
+ v = 10 * v + (int) digits[i++] - (int) '0';
+ factor *= 10;
+ }
+ if (factor != 1) {
+ multAddMe(factor, v);
+ }
+ trimLeadingZeros();
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfPow52(int p5, int p2) {
+ if (p5 != 0) {
+ if (p2 == 0) {
+ return big5pow(p5);
+ } else if (p5 < SMALL_5_POW.length) {
+ int pow5 = SMALL_5_POW[p5];
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{pow5}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ pow5 << bitcount,
+ pow5 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ return big5pow(p5).leftShift(p2);
+ }
+ } else {
+ return valueOfPow2(p2);
+ }
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ *
+ * @param value The constant factor.
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+ @*/
+ public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+ assert p5 >= 0 : p5;
+ assert p2 >= 0 : p2;
+ int v0 = (int) value;
+ int v1 = (int) (value >>> 32);
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ if (p5 != 0) {
+ if (p5 < SMALL_5_POW.length) {
+ long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+ long carry = (v0 & LONG_MASK) * pow5;
+ v0 = (int) carry;
+ carry >>>= 32;
+ carry = (v1 & LONG_MASK) * pow5 + carry;
+ v1 = (int) carry;
+ int v2 = (int) (carry >>> 32);
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+ v2 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ int[] r;
+ if (v1 == 0) {
+ r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, r);
+ } else {
+ r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+ mult(pow5.data, pow5.nWords, v0, v1, r);
+ }
+ return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+ }
+ } else if (p2 != 0) {
+ if (bitcount == 0) {
+ return new FDBigInteger(new int[]{v0, v1}, wordcount);
+ } else {
+ return new FDBigInteger(new int[]{
+ v0 << bitcount,
+ (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+ v1 >>> (32 - bitcount)
+ }, wordcount);
+ }
+ }
+ return new FDBigInteger(new int[]{v0, v1}, 0);
+ }
+
+ /**
+ * Returns an <code>FDBigInteger</code> with the numerical value
+ * <code>2<sup>p2</sup></code>.
+ *
+ * @param p2 The exponent of 2.
+ * @return <code>2<sup>p2</sup></code>
+ */
+ /*@
+ @ requires p2 >= 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == pow52(0, p2);
+ @*/
+ private static FDBigInteger valueOfPow2(int p2) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+ }
+
+ /**
+ * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
+ * the offset and number of non-zero leading words accordingly.
+ */
+ /*@
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires nWords == 0 ==> offset == 0;
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ private /*@ helper @*/ void trimLeadingZeros() {
+ int i = nWords;
+ if (i > 0 && (data[--i] == 0)) {
+ //for (; i > 0 && data[i - 1] == 0; i--) ;
+ while(i > 0 && data[i - 1] == 0) {
+ i--;
+ }
+ this.nWords = i;
+ if (i == 0) { // all words are zero
+ this.offset = 0;
+ }
+ }
+ }
+
+ /**
+ * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
+ * normalization bias is a left shift such that after it the highest word
+ * of the value will have the 4 highest bits equal to zero:
+ * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
+ * {@code (highestWord & 0x08000000) != 0}.
+ *
+ * @return The normalization bias.
+ */
+ /*@
+ @ requires this.value() > 0;
+ @*/
+ public /*@ pure @*/ int getNormalizationBias() {
+ if (nWords == 0) {
+ throw new IllegalArgumentException("Zero value cannot be normalized");
+ }
+ int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+ return (zeros < 4) ? 28 + zeros : zeros - 4;
+ }
+
+ // TODO: Why is anticount param needed if it is always 32 - bitcount?
+ /**
+ * Left shifts the contents of one int array into another.
+ *
+ * @param src The source array.
+ * @param idx The initial index of the source array.
+ * @param result The destination array.
+ * @param bitcount The left shift.
+ * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
+ * @param prev The prior source value.
+ */
+ /*@
+ @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+ @ requires src.length >= idx && result.length > idx;
+ @ assignable result[*];
+ @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+ @*/
+ private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+ for (; idx > 0; idx--) {
+ int v = (prev << bitcount);
+ prev = src[idx - 1];
+ v |= (prev >>> anticount);
+ result[idx] = v;
+ }
+ int v = prev << bitcount;
+ result[0] = v;
+ }
+
+ /**
+ * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
+ * in-place unless the <code>FDBigInteger</code> is immutable in which case
+ * a new instance of <code>FDBigInteger</code> is returned.
+ *
+ * @param shift The number of bits to shift left.
+ * @return The shifted <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0 || shift == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() << shift);
+ @*/
+ public FDBigInteger leftShift(int shift) {
+ if (shift == 0 || nWords == 0) {
+ return this;
+ }
+ int wordcount = shift >> 5;
+ int bitcount = shift & 0x1f;
+ if (this.isImmutable) {
+ if (bitcount == 0) {
+ return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+ } else {
+ int anticount = 32 - bitcount;
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result;
+ if (hi != 0) {
+ result = new int[nWords + 1];
+ result[nWords] = hi;
+ } else {
+ result = new int[nWords];
+ }
+ leftShift(data,idx,result,bitcount,anticount,prev);
+ return new FDBigInteger(result, offset + wordcount);
+ }
+ } else {
+ if (bitcount != 0) {
+ int anticount = 32 - bitcount;
+ if ((data[0] << bitcount) == 0) {
+ int idx = 0;
+ int prev = data[idx];
+ for (; idx < nWords - 1; idx++) {
+ int v = (prev >>> anticount);
+ prev = data[idx + 1];
+ v |= (prev << bitcount);
+ data[idx] = v;
+ }
+ int v = prev >>> anticount;
+ data[idx] = v;
+ if(v==0) {
+ nWords--;
+ }
+ offset++;
+ } else {
+ int idx = nWords - 1;
+ int prev = data[idx];
+ int hi = prev >>> anticount;
+ int[] result = data;
+ int[] src = data;
+ if (hi != 0) {
+ if(nWords == data.length) {
+ data = result = new int[nWords + 1];
+ }
+ result[nWords++] = hi;
+ }
+ leftShift(src,idx,result,bitcount,anticount,prev);
+ }
+ }
+ offset += wordcount;
+ return this;
+ }
+ }
+
+ /**
+ * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
+ *
+ * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ ensures \result == 0;
+ @
+ @ also
+ @
+ @ requires this.value() > 0;
+ @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+ @*/
+ private /*@ pure @*/ int size() {
+ return nWords + offset;
+ }
+
+
+ /**
+ * Computes
+ * <pre>
+ * q = (int)( this / S )
+ * this = 10 * ( this mod S )
+ * Return q.
+ * </pre>
+ * This is the iteration step of digit development for output.
+ * We assume that S has been normalized, as above, and that
+ * "this" has been left-shifted accordingly.
+ * Also assumed, of course, is that the result, q, can be expressed
+ * as an integer, {@code 0 <= q < 10}.
+ *
+ * @param S The divisor of this <code>FDBigInteger</code>.
+ * @return <code>q = (int)(this / S)</code>.
+ */
+ /*@
+ @ requires !this.isImmutable;
+ @ requires this.size() <= S.size();
+ @ requires this.data.length + this.offset >= S.size();
+ @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == \old(this.value() / S.value());
+ @ ensures this.value() == \old(10 * (this.value() % S.value()));
+ @*/
+ public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
+ assert !this.isImmutable : "cannot modify immutable value";
+ // ensure that this and S have the same number of
+ // digits. If S is properly normalized and q < 10 then
+ // this must be so.
+ int thSize = this.size();
+ int sSize = S.size();
+ if (thSize < sSize) {
+ // this value is significantly less than S, result of division is zero.
+ // just mult this by 10.
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if(p!=0) {
+ this.data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return 0;
+ } else if (thSize > sSize) {
+ throw new IllegalArgumentException("disparate values");
+ }
+ // estimate q the obvious way. We will usually be
+ // right. If not, then we're only off by a little and
+ // will re-add.
+ long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
+ long diff = multDiffMe(q, S);
+ if (diff != 0L) {
+ //@ assert q != 0;
+ //@ assert this.offset == \old(Math.min(this.offset, S.offset));
+ //@ assert this.offset <= S.offset;
+
+ // q is too big.
+ // add S back in until this turns +. This should
+ // not be very many times!
+ long sum = 0L;
+ int tStart = S.offset - this.offset;
+ //@ assert tStart >= 0;
+ int[] sd = S.data;
+ int[] td = this.data;
+ while (sum == 0L) {
+ for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
+ sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) sum;
+ sum >>>= 32; // Signed or unsigned, answer is 0 or 1
+ }
+ //
+ // Originally the following line read
+ // "if ( sum !=0 && sum != -1 )"
+ // but that would be wrong, because of the
+ // treatment of the two values as entirely unsigned,
+ // it would be impossible for a carry-out to be interpreted
+ // as -1 -- it would have to be a single-bit carry-out, or +1.
+ //
+ assert sum == 0 || sum == 1 : sum; // carry out of division correction
+ q -= 1;
+ }
+ }
+ // finally, we can multiply this by 10.
+ // it cannot overflow, right, as the high-order word has
+ // at least 4 high-order zeros!
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ assert p == 0 : p; // Carry out of *10
+ trimLeadingZeros();
+ return (int) q;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
+ * performed in place unless the <code>FDBigInteger</code> is immutable in
+ * which case a new <code>FDBigInteger</code> will be returned.
+ *
+ * @return The <code>FDBigInteger</code> multiplied by 10.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && this.isImmutable;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * 10);
+ @*/
+ public FDBigInteger multBy10() {
+ if (nWords == 0) {
+ return this;
+ }
+ if (isImmutable) {
+ int[] res = new int[nWords + 1];
+ res[nWords] = multAndCarryBy10(data, nWords, res);
+ return new FDBigInteger(res, offset);
+ } else {
+ int p = multAndCarryBy10(this.data, this.nWords, this.data);
+ if (p != 0) {
+ if (nWords == data.length) {
+ if (data[0] == 0) {
+ System.arraycopy(data, 1, data, 0, --nWords);
+ offset++;
+ } else {
+ data = Arrays.copyOf(data, data.length + 1);
+ }
+ }
+ data[nWords++] = p;
+ } else {
+ trimLeadingZeros();
+ }
+ return this;
+ }
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
+ * performed in place if possible, otherwise a new <code>FDBigInteger</code>
+ * will be returned.
+ *
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return The multiplication result.
+ */
+ /*@
+ @ requires this.value() == 0 || p5 == 0 && p2 == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @
+ @ also
+ @
+ @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
+ @ assignable this.nWords, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
+ @*/
+ public FDBigInteger multByPow52(int p5, int p2) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ FDBigInteger res = this;
+ if (p5 != 0) {
+ int[] r;
+ int extraSize = (p2 != 0) ? 1 : 0;
+ if (p5 < SMALL_5_POW.length) {
+ r = new int[this.nWords + 1 + extraSize];
+ mult(this.data, this.nWords, SMALL_5_POW[p5], r);
+ res = new FDBigInteger(r, this.offset);
+ } else {
+ FDBigInteger pow5 = big5pow(p5);
+ r = new int[this.nWords + pow5.size() + extraSize];
+ mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
+ res = new FDBigInteger(r, this.offset + pow5.offset);
+ }
+ }
+ return res.leftShift(p2);
+ }
+
+ /**
+ * Multiplies two big integers represented as int arrays.
+ *
+ * @param s1 The first array factor.
+ * @param s1Len The number of elements of <code>s1</code> to use.
+ * @param s2 The second array factor.
+ * @param s2Len The number of elements of <code>s2</code> to use.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires s1 != dst && s2 != dst;
+ @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
+ @ assignable dst[0 .. s1Len + s2Len - 1];
+ @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
+ @*/
+ private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
+ for (int i = 0; i < s1Len; i++) {
+ long v = s1[i] & LONG_MASK;
+ long p = 0L;
+ for (int j = 0; j < s2Len; j++) {
+ p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
+ dst[i + j] = (int) p;
+ p >>>= 32;
+ }
+ dst[i + s2Len] = (int) p;
+ }
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the subtrahend is immutable, store the result in this(minuend).
+ * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires this.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures \result == this;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend;
+ if (this.isImmutable) {
+ minuend = new FDBigInteger(this.data.clone(), this.offset);
+ } else {
+ minuend = this;
+ }
+ int offsetDiff = subtrahend.offset - minuend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ // need to expand minuend
+ int rLen = minLen - offsetDiff;
+ if (rLen < mData.length) {
+ System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
+ Arrays.fill(mData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(mData, 0, r, -offsetDiff, minLen);
+ minuend.data = mData = r;
+ }
+ minuend.offset = subtrahend.offset;
+ minuend.nWords = minLen = rLen;
+ offsetDiff = 0;
+ }
+ long borrow = 0L;
+ int mIndex = offsetDiff;
+ for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ for (; borrow != 0 && mIndex < minLen; mIndex++) {
+ long diff = (mData[mIndex] & LONG_MASK) + borrow;
+ mData[mIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ minuend.trimLeadingZeros();
+ return minuend;
+ }
+
+ /**
+ * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
+ * <code>FDBigInteger</code>. Assert that the result is positive.
+ * If the this(minuend) is immutable, store the result in subtrahend.
+ * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
+ *
+ * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
+ * @return This <code>FDBigInteger</code> less the subtrahend.
+ */
+ /*@
+ @ requires subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @
+ @ also
+ @
+ @ requires !subtrahend.isImmutable;
+ @ requires this.value() >= subtrahend.value();
+ @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
+ @ ensures \result == subtrahend;
+ @ ensures \result.value() == \old(this.value() - subtrahend.value());
+ @*/
+ public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
+ assert this.size() >= subtrahend.size() : "result should be positive";
+ FDBigInteger minuend = this;
+ if (subtrahend.isImmutable) {
+ subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
+ }
+ int offsetDiff = minuend.offset - subtrahend.offset;
+ int[] sData = subtrahend.data;
+ int[] mData = minuend.data;
+ int subLen = subtrahend.nWords;
+ int minLen = minuend.nWords;
+ if (offsetDiff < 0) {
+ int rLen = minLen;
+ if (rLen < sData.length) {
+ System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
+ Arrays.fill(sData, 0, -offsetDiff, 0);
+ } else {
+ int[] r = new int[rLen];
+ System.arraycopy(sData, 0, r, -offsetDiff, subLen);
+ subtrahend.data = sData = r;
+ }
+ subtrahend.offset = minuend.offset;
+ subLen -= offsetDiff;
+ offsetDiff = 0;
+ } else {
+ int rLen = minLen + offsetDiff;
+ if (rLen >= sData.length) {
+ subtrahend.data = sData = Arrays.copyOf(sData, rLen);
+ }
+ }
+ //@ assert minuend == this && minuend.value() == \old(this.value());
+ //@ assert mData == minuend.data && minLen == minuend.nWords;
+ //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
+ //@ assert sData == subtrahend.data;
+ //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
+ //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
+ //@ assert offsetDiff == minuend.offset - subtrahend.offset;
+ //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
+ int sIndex = 0;
+ long borrow = 0L;
+ for (; sIndex < offsetDiff; sIndex++) {
+ long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ //@ assert sIndex == offsetDiff;
+ for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
+ //@ assert sIndex == offsetDiff + mIndex;
+ long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
+ sData[sIndex] = (int) diff;
+ borrow = diff >> 32; // signed shift
+ }
+ assert borrow == 0L : borrow; // borrow out of subtract,
+ // result should be positive
+ subtrahend.nWords = sIndex;
+ subtrahend.trimLeadingZeros();
+ return subtrahend;
+
+ }
+
+ /**
+ * Determines whether all elements of an array are zero for all indices less
+ * than a given index.
+ *
+ * @param a The array to be examined.
+ * @param from The index strictly below which elements are to be examined.
+ * @return Zero if all elements in range are zero, 1 otherwise.
+ */
+ /*@
+ @ requires 0 <= from && from <= a.length;
+ @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
+ @*/
+ private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
+ while (from > 0) {
+ if (a[--from] != 0) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Compares the parameter with this <code>FDBigInteger</code>. Returns an
+ * integer accordingly as:
+ * <pre>{@code
+ * > 0: this > other
+ * 0: this == other
+ * < 0: this < other
+ * }</pre>
+ *
+ * @param other The <code>FDBigInteger</code> to compare.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmp(FDBigInteger other) {
+ int aSize = nWords + offset;
+ int bSize = other.nWords + other.offset;
+ if (aSize > bSize) {
+ return 1;
+ } else if (aSize < bSize) {
+ return -1;
+ }
+ int aLen = nWords;
+ int bLen = other.nWords;
+ while (aLen > 0 && bLen > 0) {
+ int a = data[--aLen];
+ int b = other.data[--bLen];
+ if (a != b) {
+ return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ }
+ if (aLen > 0) {
+ return checkZeroTail(data, aLen);
+ }
+ if (bLen > 0) {
+ return -checkZeroTail(other.data, bLen);
+ }
+ return 0;
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with
+ * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
+ * Returns an integer accordingly as:
+ * <pre>{@code
+ * > 0: this > other
+ * 0: this == other
+ * < 0: this < other
+ * }</pre>
+ * @param p5 The exponent of the power-of-five factor.
+ * @param p2 The exponent of the power-of-two factor.
+ * @return A negative value, zero, or a positive value according to the
+ * result of the comparison.
+ */
+ /*@
+ @ requires p5 >= 0 && p2 >= 0;
+ @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int cmpPow52(int p5, int p2) {
+ if (p5 == 0) {
+ int wordcount = p2 >> 5;
+ int bitcount = p2 & 0x1f;
+ int size = this.nWords + this.offset;
+ if (size > wordcount + 1) {
+ return 1;
+ } else if (size < wordcount + 1) {
+ return -1;
+ }
+ int a = this.data[this.nWords -1];
+ int b = 1 << bitcount;
+ if (a != b) {
+ return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
+ }
+ return checkZeroTail(this.data, this.nWords - 1);
+ }
+ return this.cmp(big5pow(p5).leftShift(p2));
+ }
+
+ /**
+ * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
+ * value according to the comparison as:
+ * <pre>{@code
+ * -1: this < x + y
+ * 0: this == x + y
+ * 1: this > x + y
+ * }</pre>
+ * @param x The first addend of the sum to compare.
+ * @param y The second addend of the sum to compare.
+ * @return -1, 0, or 1 according to the result of the comparison.
+ */
+ /*@
+ @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
+ @*/
+ public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
+ FDBigInteger big;
+ FDBigInteger small;
+ int xSize = x.size();
+ int ySize = y.size();
+ int bSize;
+ int sSize;
+ if (xSize >= ySize) {
+ big = x;
+ small = y;
+ bSize = xSize;
+ sSize = ySize;
+ } else {
+ big = y;
+ small = x;
+ bSize = ySize;
+ sSize = xSize;
+ }
+ int thSize = this.size();
+ if (bSize == 0) {
+ return thSize == 0 ? 0 : 1;
+ }
+ if (sSize == 0) {
+ return this.cmp(big);
+ }
+ if (bSize > thSize) {
+ return -1;
+ }
+ if (bSize + 1 < thSize) {
+ return 1;
+ }
+ long top = (big.data[big.nWords - 1] & LONG_MASK);
+ if (sSize == bSize) {
+ top += (small.data[small.nWords - 1] & LONG_MASK);
+ }
+ if ((top >>> 32) == 0) {
+ if (((top + 1) >>> 32) == 0) {
+ // good case - no carry extension
+ if (bSize < thSize) {
+ return 1;
+ }
+ // here sum.nWords == this.nWords
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ } else { // (top>>>32)!=0 guaranteed carry extension
+ if (bSize + 1 > thSize) {
+ return -1;
+ }
+ // here sum.nWords == this.nWords
+ top >>>= 32;
+ long v = (this.data[this.nWords - 1] & LONG_MASK);
+ if (v < top) {
+ return -1;
+ }
+ if (v > top + 1) {
+ return 1;
+ }
+ }
+ return this.cmp(big.add(small));
+ }
+
+ /**
+ * Makes this <code>FDBigInteger</code> immutable.
+ */
+ /*@
+ @ assignable this.isImmutable;
+ @ ensures this.isImmutable;
+ @*/
+ public void makeImmutable() {
+ this.isImmutable = true;
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by an integer.
+ *
+ * @param i The factor by which to multiply this <code>FDBigInteger</code>.
+ * @return This <code>FDBigInteger</code> multiplied by an integer.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
+ @*/
+ private FDBigInteger mult(int i) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ int[] r = new int[nWords + 1];
+ mult(data, nWords, i, r);
+ return new FDBigInteger(r, offset);
+ }
+
+ /**
+ * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> factor by which to multiply.
+ * @return The product of this and the parameter <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ requires this.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == this;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() == 0;
+ @ assignable \nothing;
+ @ ensures \result == other;
+ @
+ @ also
+ @
+ @ requires this.value() != 0 && other.value() != 0;
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() * other.value());
+ @*/
+ private FDBigInteger mult(FDBigInteger other) {
+ if (this.nWords == 0) {
+ return this;
+ }
+ if (this.size() == 1) {
+ return other.mult(data[0]);
+ }
+ if (other.nWords == 0) {
+ return other;
+ }
+ if (other.size() == 1) {
+ return this.mult(other.data[0]);
+ }
+ int[] r = new int[nWords + other.nWords];
+ mult(this.data, this.nWords, other.data, other.nWords, r);
+ return new FDBigInteger(r, this.offset + other.offset);
+ }
+
+ /**
+ * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
+ *
+ * @param other The <code>FDBigInteger</code> to add.
+ * @return The sum of the <code>FDBigInteger</code>s.
+ */
+ /*@
+ @ assignable \nothing;
+ @ ensures \result.value() == \old(this.value() + other.value());
+ @*/
+ private FDBigInteger add(FDBigInteger other) {
+ FDBigInteger big, small;
+ int bigLen, smallLen;
+ int tSize = this.size();
+ int oSize = other.size();
+ if (tSize >= oSize) {
+ big = this;
+ bigLen = tSize;
+ small = other;
+ smallLen = oSize;
+ } else {
+ big = other;
+ bigLen = oSize;
+ small = this;
+ smallLen = tSize;
+ }
+ int[] r = new int[bigLen + 1];
+ int i = 0;
+ long carry = 0L;
+ for (; i < smallLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
+ + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ for (; i < bigLen; i++) {
+ carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
+ r[i] = (int) carry;
+ carry >>= 32; // signed shift.
+ }
+ r[bigLen] = (int) carry;
+ return new FDBigInteger(r, 0);
+ }
+
+
+ /**
+ * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
+ * result is computed in place. This method is intended only to be invoked
+ * from
+ * <code>
+ * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
+ * </code>.
+ *
+ * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
+ * @param addend The value to add to the product of this
+ * <code>FDBigInteger</code> and <code>iv</code>.
+ */
+ /*@
+ @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
+ @ assignable this.data[*];
+ @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
+ @*/
+ private /*@ helper @*/ void multAddMe(int iv, int addend) {
+ long v = iv & LONG_MASK;
+ // unroll 0th iteration, doing addition.
+ long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
+ data[0] = (int) p;
+ p >>>= 32;
+ for (int i = 1; i < nWords; i++) {
+ p += v * (data[i] & LONG_MASK);
+ data[i] = (int) p;
+ p >>>= 32;
+ }
+ if (p != 0L) {
+ data[nWords++] = (int) p; // will fail noisily if illegal!
+ }
+ }
+
+ //
+ // original doc:
+ //
+ // do this -=q*S
+ // returns borrow
+ //
+ /**
+ * Multiplies the parameters and subtracts them from this
+ * <code>FDBigInteger</code>.
+ *
+ * @param q The integer parameter.
+ * @param S The <code>FDBigInteger</code> parameter.
+ * @return <code>this - q*S</code>.
+ */
+ /*@
+ @ ensures nWords == 0 ==> offset == 0;
+ @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+ @*/
+ /*@
+ @ requires 0 < q && q <= (1L << 31);
+ @ requires data != null;
+ @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+ @ requires !this.isImmutable;
+ @ requires this.size() == S.size();
+ @ requires this != S;
+ @ assignable this.nWords, this.offset, this.data, this.data[*];
+ @ ensures -q <= \result && \result <= 0;
+ @ ensures this.size() == \old(this.size());
+ @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
+ @ ensures this.offset == \old(Math.min(this.offset, S.offset));
+ @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
+ @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
+ @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
+ @
+ @ also
+ @
+ @ requires q == 0;
+ @ assignable \nothing;
+ @ ensures \result == 0;
+ @*/
+ private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
+ long diff = 0L;
+ if (q != 0) {
+ int deltaSize = S.offset - this.offset;
+ if (deltaSize >= 0) {
+ int[] sd = S.data;
+ int[] td = this.data;
+ for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ td[tIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ } else {
+ deltaSize = -deltaSize;
+ int[] rd = new int[nWords + deltaSize];
+ int sIndex = 0;
+ int rIndex = 0;
+ int[] sd = S.data;
+ for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
+ diff -= q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ int tIndex = 0;
+ int[] td = this.data;
+ for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
+ diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
+ rd[rIndex] = (int) diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ this.nWords += deltaSize;
+ this.offset -= deltaSize;
+ this.data = rd;
+ }
+ }
+ return diff;
+ }
+
+
+ /**
+ * Multiplies by 10 a big integer represented as an array. The final carry
+ * is returned.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param dst The product array.
+ * @return The final carry of the multiplication.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen;
+ @ assignable dst[0 .. srcLen - 1];
+ @ ensures 0 <= \result && \result < 10;
+ @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
+ @*/
+ private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * 10L + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ return (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is an <code>int</code>.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param value The constant factor by which to multiply.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src.length >= srcLen && dst.length >= srcLen + 1;
+ @ assignable dst[0 .. srcLen];
+ @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
+ @*/
+ private static void mult(int[] src, int srcLen, int value, int[] dst) {
+ long val = value & LONG_MASK;
+ long carry = 0;
+ for (int i = 0; i < srcLen; i++) {
+ long product = (src[i] & LONG_MASK) * val + carry;
+ dst[i] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ }
+
+ /**
+ * Multiplies by a constant value a big integer represented as an array.
+ * The constant factor is a long represent as two <code>int</code>s.
+ *
+ * @param src The array representation of the big integer.
+ * @param srcLen The number of elements of <code>src</code> to use.
+ * @param v0 The lower 32 bits of the long factor.
+ * @param v1 The upper 32 bits of the long factor.
+ * @param dst The product array.
+ */
+ /*@
+ @ requires src != dst;
+ @ requires src.length >= srcLen && dst.length >= srcLen + 2;
+ @ assignable dst[0 .. srcLen + 1];
+ @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
+ @*/
+ private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
+ long v = v0 & LONG_MASK;
+ long carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = v * (src[j] & LONG_MASK) + carry;
+ dst[j] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen] = (int) carry;
+ v = v1 & LONG_MASK;
+ carry = 0;
+ for (int j = 0; j < srcLen; j++) {
+ long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
+ dst[j + 1] = (int) product;
+ carry = product >>> 32;
+ }
+ dst[srcLen + 1] = (int) carry;
+ }
+
+ // Fails assertion for negative exponent.
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5pow(int p) {
+ assert p >= 0 : p; // negative power of 5
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ return big5powRec(p);
+ }
+
+ // slow path
+ /**
+ * Computes <code>5</code> raised to a given power.
+ *
+ * @param p The exponent of 5.
+ * @return <code>5<sup>p</sup></code>.
+ */
+ private static FDBigInteger big5powRec(int p) {
+ if (p < MAX_FIVE_POW) {
+ return POW_5_CACHE[p];
+ }
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ FDBigInteger bigq = big5powRec(q);
+ if (r < SMALL_5_POW.length) {
+ return bigq.mult(SMALL_5_POW[r]);
+ } else {
+ return bigq.mult(big5powRec(r));
+ }
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a hexadecimal string.
+ *
+ * @return The hexadecimal string representation.
+ */
+ public String toHexString(){
+ if(nWords ==0) {
+ return "0";
+ }
+ StringBuilder sb = new StringBuilder((nWords +offset)*8);
+ for(int i= nWords -1; i>=0; i--) {
+ String subStr = Integer.toHexString(data[i]);
+ for(int j = subStr.length(); j<8; j++) {
+ sb.append('0');
+ }
+ sb.append(subStr);
+ }
+ for(int i=offset; i>0; i--) {
+ sb.append("00000000");
+ }
+ return sb.toString();
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
+ *
+ * @return The <code>BigInteger</code> representation.
+ */
+ public BigInteger toBigInteger() {
+ byte[] magnitude = new byte[nWords * 4 + 1];
+ for (int i = 0; i < nWords; i++) {
+ int w = data[i];
+ magnitude[magnitude.length - 4 * i - 1] = (byte) w;
+ magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
+ magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
+ magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
+ }
+ return new BigInteger(magnitude).shiftLeft(offset * 32);
+ }
+
+ // for debugging ...
+ /**
+ * Converts this <code>FDBigInteger</code> to a string.
+ *
+ * @return The string representation.
+ */
+ @Override
+ public String toString(){
+ return toBigInteger().toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatConsts.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2003, 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. 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.math;
+
+/**
+ * This class contains additional constants documenting limits of the
+ * <code>float</code> type.
+ *
+ * @author Joseph D. Darcy
+ */
+
+public class FloatConsts {
+ /**
+ * Don't let anyone instantiate this class.
+ */
+ private FloatConsts() {}
+
+ public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
+ public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
+ public static final float NaN = java.lang.Float.NaN;
+ public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
+ public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
+
+ /**
+ * A constant holding the smallest positive normal value of type
+ * <code>float</code>, 2<sup>-126</sup>. It is equal to the value
+ * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
+ */
+ public static final float MIN_NORMAL = 1.17549435E-38f;
+
+ /**
+ * The number of logical bits in the significand of a
+ * <code>float</code> number, including the implicit bit.
+ */
+ public static final int SIGNIFICAND_WIDTH = 24;
+
+ /**
+ * Maximum exponent a finite <code>float</code> number may have.
+ * It is equal to the value returned by
+ * <code>Math.ilogb(Float.MAX_VALUE)</code>.
+ */
+ public static final int MAX_EXPONENT = 127;
+
+ /**
+ * Minimum exponent a normalized <code>float</code> number may
+ * have. It is equal to the value returned by
+ * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
+ */
+ public static final int MIN_EXPONENT = -126;
+
+ /**
+ * The exponent the smallest positive <code>float</code> subnormal
+ * value would have if it could be normalized.
+ */
+ public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
+ (SIGNIFICAND_WIDTH - 1);
+
+ /**
+ * Bias used in representing a <code>float</code> exponent.
+ */
+ public static final int EXP_BIAS = 127;
+
+ /**
+ * Bit mask to isolate the sign bit of a <code>float</code>.
+ */
+ public static final int SIGN_BIT_MASK = 0x80000000;
+
+ /**
+ * Bit mask to isolate the exponent field of a
+ * <code>float</code>.
+ */
+ public static final int EXP_BIT_MASK = 0x7F800000;
+
+ /**
+ * Bit mask to isolate the significand field of a
+ * <code>float</code>.
+ */
+ public static final int SIGNIF_BIT_MASK = 0x007FFFFF;
+
+ static {
+ // verify bit masks cover all bit positions and that the bit
+ // masks are non-overlapping
+ assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
+ (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
+ ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
+ ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,2552 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal.math;
+
+import java.util.Arrays;
+import java.util.regex.*;
+
+/**
+ * A class for converting between ASCII and decimal representations of a single
+ * or double precision floating point number. Most conversions are provided via
+ * static convenience methods, although a <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
+public class FloatingDecimal{
+ //
+ // Constants of the implementation;
+ // most are IEEE-754 related.
+ // (There are more really boring constants at the end.)
+ //
+ static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
+ static final long FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
+ static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
+ static final int MAX_SMALL_BIN_EXP = 62;
+ static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
+ static final int MAX_DECIMAL_DIGITS = 15;
+ static final int MAX_DECIMAL_EXPONENT = 308;
+ static final int MIN_DECIMAL_EXPONENT = -324;
+ static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
+ static final int MAX_NDIGITS = 1100;
+
+ static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
+ static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
+ static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
+ static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
+ static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
+ static final int SINGLE_MAX_NDIGITS = 200;
+
+ static final int INT_DECIMAL_DIGITS = 9;
+
+ /**
+ * Converts a double precision floating point value to a <code>String</code>.
+ *
+ * @param d The double precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(double d) {
+ return getBinaryToASCIIConverter(d).toJavaFormatString();
+ }
+
+ /**
+ * Converts a single precision floating point value to a <code>String</code>.
+ *
+ * @param f The single precision value.
+ * @return The value converted to a <code>String</code>.
+ */
+ public static String toJavaFormatString(float f) {
+ return getBinaryToASCIIConverter(f).toJavaFormatString();
+ }
+
+ /**
+ * Appends a double precision floating point value to an <code>Appendable</code>.
+ * @param d The double precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(double d, Appendable buf) {
+ getBinaryToASCIIConverter(d).appendTo(buf);
+ }
+
+ /**
+ * Appends a single precision floating point value to an <code>Appendable</code>.
+ * @param f The single precision value.
+ * @param buf The <code>Appendable</code> with the value appended.
+ */
+ public static void appendTo(float f, Appendable buf) {
+ getBinaryToASCIIConverter(f).appendTo(buf);
+ }
+
+ /**
+ * Converts a <code>String</code> to a double precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The double precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted double precision value.
+ */
+ public static double parseDouble(String s) throws NumberFormatException {
+ return readJavaFormatString(s).doubleValue();
+ }
+
+ /**
+ * Converts a <code>String</code> to a single precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The single precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted single precision value.
+ */
+ public static float parseFloat(String s) throws NumberFormatException {
+ return readJavaFormatString(s).floatValue();
+ }
+
+ /**
+ * A converter which can process single or double precision floating point
+ * values into an ASCII <code>String</code> representation.
+ */
+ public interface BinaryToASCIIConverter {
+ /**
+ * Converts a floating point value into an ASCII <code>String</code>.
+ * @return The value converted to a <code>String</code>.
+ */
+ public String toJavaFormatString();
+
+ /**
+ * Appends a floating point value to an <code>Appendable</code>.
+ * @param buf The <code>Appendable</code> to receive the value.
+ */
+ public void appendTo(Appendable buf);
+
+ /**
+ * Retrieves the decimal exponent most closely corresponding to this value.
+ * @return The decimal exponent.
+ */
+ public int getDecimalExponent();
+
+ /**
+ * Retrieves the value as an array of digits.
+ * @param digits The digit array.
+ * @return The number of valid digits copied into the array.
+ */
+ public int getDigits(char[] digits);
+
+ /**
+ * Indicates the sign of the value.
+ * @return {@code value < 0.0}.
+ */
+ public boolean isNegative();
+
+ /**
+ * Indicates whether the value is either infinite or not a number.
+ *
+ * @return <code>true</code> if and only if the value is <code>NaN</code>
+ * or infinite.
+ */
+ public boolean isExceptional();
+
+ /**
+ * Indicates whether the value was rounded up during the binary to ASCII
+ * conversion.
+ *
+ * @return <code>true</code> if and only if the value was rounded up.
+ */
+ public boolean digitsRoundedUp();
+
+ /**
+ * Indicates whether the binary to ASCII conversion was exact.
+ *
+ * @return <code>true</code> if any only if the conversion was exact.
+ */
+ public boolean decimalDigitsExact();
+ }
+
+ /**
+ * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
+ * and infinite values.
+ */
+ private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ private final String image;
+ private boolean isNegative;
+
+ public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
+ this.image = image;
+ this.isNegative = isNegative;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ return image;
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(image);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(image);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ throw new IllegalArgumentException("Exceptional value does not have an exponent");
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ throw new IllegalArgumentException("Exceptional value does not have digits");
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return true;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ throw new IllegalArgumentException("Exceptional value is not rounded");
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ throw new IllegalArgumentException("Exceptional value is not exact");
+ }
+ }
+
+ private static final String INFINITY_REP = "Infinity";
+ private static final int INFINITY_LENGTH = INFINITY_REP.length();
+ private static final String NAN_REP = "NaN";
+ private static final int NAN_LENGTH = NAN_REP.length();
+
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
+ private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
+ private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
+ private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
+
+ /**
+ * A buffered implementation of <code>BinaryToASCIIConverter</code>.
+ */
+ static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
+ private boolean isNegative;
+ private int decExponent;
+ private int firstDigitIndex;
+ private int nDigits;
+ private final char[] digits;
+ private final char[] buffer = new char[26];
+
+ //
+ // The fields below provide additional information about the result of
+ // the binary to decimal digits conversion done in dtoa() and roundup()
+ // methods. They are changed if needed by those two methods.
+ //
+
+ // True if the dtoa() binary to decimal conversion was exact.
+ private boolean exactDecimalConversion = false;
+
+ // True if the result of the binary to decimal conversion was rounded-up
+ // at the end of the conversion process, i.e. roundUp() method was called.
+ private boolean decimalDigitsRoundedUp = false;
+
+ /**
+ * Default constructor; used for non-zero values,
+ * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
+ */
+ BinaryToASCIIBuffer(){
+ this.digits = new char[20];
+ }
+
+ /**
+ * Creates a specialized value (positive and negative zeros).
+ */
+ BinaryToASCIIBuffer(boolean isNegative, char[] digits){
+ this.isNegative = isNegative;
+ this.decExponent = 0;
+ this.digits = digits;
+ this.firstDigitIndex = 0;
+ this.nDigits = digits.length;
+ }
+
+ @Override
+ public String toJavaFormatString() {
+ int len = getChars(buffer);
+ return new String(buffer, 0, len);
+ }
+
+ @Override
+ public void appendTo(Appendable buf) {
+ int len = getChars(buffer);
+ if (buf instanceof StringBuilder) {
+ ((StringBuilder) buf).append(buffer, 0, len);
+ } else if (buf instanceof StringBuffer) {
+ ((StringBuffer) buf).append(buffer, 0, len);
+ } else {
+ assert false;
+ }
+ }
+
+ @Override
+ public int getDecimalExponent() {
+ return decExponent;
+ }
+
+ @Override
+ public int getDigits(char[] digits) {
+ System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
+ return this.nDigits;
+ }
+
+ @Override
+ public boolean isNegative() {
+ return isNegative;
+ }
+
+ @Override
+ public boolean isExceptional() {
+ return false;
+ }
+
+ @Override
+ public boolean digitsRoundedUp() {
+ return decimalDigitsRoundedUp;
+ }
+
+ @Override
+ public boolean decimalDigitsExact() {
+ return exactDecimalConversion;
+ }
+
+ private void setSign(boolean isNegative) {
+ this.isNegative = isNegative;
+ }
+
+ /**
+ * This is the easy subcase --
+ * all the significant bits, after scaling, are held in lvalue.
+ * negSign and decExponent tell us what processing and scaling
+ * has already been done. Exceptional cases have already been
+ * stripped out.
+ * In particular:
+ * lvalue is a finite number (not Inf, nor NaN)
+ * lvalue > 0L (not zero, nor negative).
+ *
+ * The only reason that we develop the digits here, rather than
+ * calling on Long.toString() is that we can do it a little faster,
+ * and besides want to treat trailing 0s specially. If Long.toString
+ * changes, we should re-evaluate this strategy!
+ */
+ private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
+ if ( insignificantDigits != 0 ){
+ // Discard non-significant low-order bits, while rounding,
+ // up to insignificant value.
+ long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
+ long residue = lvalue % pow10;
+ lvalue /= pow10;
+ decExponent += insignificantDigits;
+ if ( residue >= (pow10>>1) ){
+ // round up based on the low-order bits we're discarding
+ lvalue++;
+ }
+ }
+ int digitno = digits.length -1;
+ int c;
+ if ( lvalue <= Integer.MAX_VALUE ){
+ assert lvalue > 0L : lvalue; // lvalue <= 0
+ // even easier subcase!
+ // can do int arithmetic rather than long!
+ int ivalue = (int)lvalue;
+ c = ivalue%10;
+ ivalue /= 10;
+ while ( c == 0 ){
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ while ( ivalue != 0){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ } else {
+ // same algorithm as above (same bugs, too )
+ // but using long arithmetic.
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ while ( c == 0 ){
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ }
+ while ( lvalue != 0L ){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ }
+ this.decExponent = decExponent+1;
+ this.firstDigitIndex = digitno;
+ this.nDigits = this.digits.length - digitno;
+ }
+
+ private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
+ {
+ assert fractBits > 0 ; // fractBits here can't be zero or negative
+ assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ final int tailZeros = Long.numberOfTrailingZeros(fractBits);
+
+ // number of significant bits of fractBits;
+ final int nFractBits = EXP_SHIFT+1-tailZeros;
+
+ // reset flags to default values as dtoa() does not always set these
+ // flags and a prior call to dtoa() might have set them to incorrect
+ // values with respect to the current state.
+ decimalDigitsRoundedUp = false;
+ exactDecimalConversion = false;
+
+ // number of significant bits to the right of the point.
+ int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
+ //
+ // We can do this:
+ // take the fraction bits, which are normalized.
+ // (a) nTinyBits == 0: Shift left or right appropriately
+ // to align the binary point at the extreme right, i.e.
+ // where a long int point is expected to be. The integer
+ // result is easily converted to a string.
+ // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
+ // which effectively converts to long and scales by
+ // 2^nTinyBits. Then multiply by 5^nTinyBits to
+ // complete the scaling. We know this won't overflow
+ // because we just counted the number of bits necessary
+ // in the result. The integer you get from this can
+ // then be converted to a string pretty easily.
+ //
+ if ( nTinyBits == 0 ) {
+ int insignificant;
+ if ( binExp > nSignificantBits ){
+ insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
+ } else {
+ insignificant = 0;
+ }
+ if ( binExp >= EXP_SHIFT ){
+ fractBits <<= (binExp-EXP_SHIFT);
+ } else {
+ fractBits >>>= (EXP_SHIFT-binExp) ;
+ }
+ developLongDigits( 0, fractBits, insignificant );
+ return;
+ }
+ //
+ // The following causes excess digits to be printed
+ // out in the single-float case. Our manipulation of
+ // halfULP here is apparently not correct. If we
+ // better understand how this works, perhaps we can
+ // use this special case again. But for the time being,
+ // we do not.
+ // else {
+ // fractBits >>>= EXP_SHIFT+1-nFractBits;
+ // fractBits//= long5pow[ nTinyBits ];
+ // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
+ // return;
+ // }
+ //
+ }
+ }
+ //
+ // This is the hard case. We are going to compute large positive
+ // integers B and S and integer decExp, s.t.
+ // d = ( B / S )// 10^decExp
+ // 1 <= B / S < 10
+ // Obvious choices are:
+ // decExp = floor( log10(d) )
+ // B = d// 2^nTinyBits// 10^max( 0, -decExp )
+ // S = 10^max( 0, decExp)// 2^nTinyBits
+ // (noting that nTinyBits has already been forced to non-negative)
+ // I am also going to compute a large positive integer
+ // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
+ // i.e. M is (1/2) of the ULP of d, scaled like B.
+ // When we iterate through dividing B/S and picking off the
+ // quotient bits, we will know when to stop when the remainder
+ // is <= M.
+ //
+ // We keep track of powers of 2 and powers of 5.
+ //
+ int decExp = estimateDecExp(fractBits,binExp);
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ //
+ // the long integer fractBits contains the (nFractBits) interesting
+ // bits from the mantissa of d ( hidden 1 added if necessary) followed
+ // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
+ // I will shift out those zeros before turning fractBits into a
+ // FDBigInteger. The resulting whole number will be
+ // d * 2^(nFractBits-1-binExp).
+ //
+ fractBits >>>= tailZeros;
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ //
+ // HACK!! For exact powers of two, the next smallest number
+ // is only half as far away as we think (because the meaning of
+ // ULP changes at power-of-two bounds) for this reason, we
+ // hack M2. Hope this works.
+ //
+ if ( nFractBits == 1 ) {
+ M2 -= 1;
+ }
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ //
+ // Construct, Scale, iterate.
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ //
+ // Detect the special cases where all the numbers we are about
+ // to compute will fit in int or long integers.
+ // In these cases, we will avoid doing FDBigInteger arithmetic.
+ // We use the same algorithms, except that we "normalize"
+ // our FDBigIntegers before iterating. This is to make division easier,
+ // as it makes our fist guess (quotient of high-order words)
+ // more accurate!
+ //
+ // Some day, we'll write a stopping test that takes
+ // account of the asymmetry of the spacing of floating-point
+ // numbers below perfect powers of 2
+ // 26 Sept 96 is not that day.
+ // So we use a symmetric test.
+ //
+ // binary digits needed to represent B, approx.
+ int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
+
+ // binary digits needed to represent 10*S, approx.
+ int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
+ int s = FDBigInteger.SMALL_5_POW[S5] << S2;
+ int m = FDBigInteger.SMALL_5_POW[M5] << M2;
+ int tens = s * 10;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
+ long s = FDBigInteger.LONG_5_POW[S5] << S2;
+ long m = FDBigInteger.LONG_5_POW[M5] << M2;
+ long tens = s * 10L;
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ }
+ } else {
+ //
+ // We really must do FDBigInteger arithmetic.
+ // Fist, construct our FDBigInteger initial values.
+ //
+ FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
+ int shiftBias = Sval.getNormalizationBias();
+ Sval = Sval.leftShift(shiftBias); // normalize so that division works better
+
+ FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
+ FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
+
+ FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
+ //
+ // Unroll the first iteration. If our decExp estimate
+ // was too high, our first quotient will be zero. In this
+ // case, we discard it and decrement decExp.
+ //
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ //
+ // HACK! Java spec sez that we always have at least
+ // one digit after the . in either F- or E-form output.
+ // Thus we will need more than one digit if we're using
+ // E-form
+ //
+ if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ assert q < 10 : q; // excessively large digit
+ Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = tenSval.addAndCmp(Bval,Mval)<=0;
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval = Bval.leftShift(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else {
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0);
+ }
+ this.decExponent = decExp+1;
+ this.firstDigitIndex = 0;
+ this.nDigits = ndigit;
+ //
+ // Last digit gets rounded based on stopping condition.
+ //
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
+ roundup();
+ }
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ // add one to the least significant digit.
+ // in the unlikely event there is a carry out, deal with it.
+ // assert that this will only happen where there
+ // is only one digit, e.g. (float)1e-44 seems to do it.
+ //
+ private void roundup() {
+ int i = (firstDigitIndex + nDigits - 1);
+ int q = digits[i];
+ if (q == '9') {
+ while (q == '9' && i > firstDigitIndex) {
+ digits[i] = '0';
+ q = digits[--i];
+ }
+ if (q == '9') {
+ // carryout! High-order 1, rest 0s, larger exp.
+ decExponent += 1;
+ digits[firstDigitIndex] = '1';
+ return;
+ }
+ // else fall through.
+ }
+ digits[i] = (char) (q + 1);
+ decimalDigitsRoundedUp = true;
+ }
+
+ /**
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ */
+ static int estimateDecExp(long fractBits, int binExp) {
+ double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
+ double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
+ long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw
+ int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
+ boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ if(exponent>=0 && exponent<52) { // hot path
+ long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
+ int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
+ return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
+ } else if (exponent < 0) {
+ return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
+ ( (isNegative) ? -1 : 0) );
+ } else { //if (exponent >= 52)
+ return (int)d;
+ }
+ }
+
+ private static int insignificantDigits(int insignificant) {
+ int i;
+ for ( i = 0; insignificant >= 10L; i++ ) {
+ insignificant /= 10L;
+ }
+ return i;
+ }
+
+ /**
+ * Calculates
+ * <pre>
+ * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
+ * </pre>
+ */
+ private static int insignificantDigitsForPow2(int p2) {
+ if(p2>1 && p2 < insignificantDigitsNumber.length) {
+ return insignificantDigitsNumber[p2];
+ }
+ return 0;
+ }
+
+ /**
+ * If insignificant==(1L << ixd)
+ * i = insignificantDigitsNumber[idx] is the same as:
+ * int i;
+ * for ( i = 0; insignificant >= 10L; i++ )
+ * insignificant /= 10L;
+ */
+ private static int[] insignificantDigitsNumber = {
+ 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+ 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+ 12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+ 15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+ 18, 18, 18, 19
+ };
+
+ // approximately ceil( log2( long5pow[i] ) )
+ private static final int[] N_5_BITS = {
+ 0,
+ 3,
+ 5,
+ 7,
+ 10,
+ 12,
+ 14,
+ 17,
+ 19,
+ 21,
+ 24,
+ 26,
+ 28,
+ 31,
+ 33,
+ 35,
+ 38,
+ 40,
+ 42,
+ 45,
+ 47,
+ 49,
+ 52,
+ 54,
+ 56,
+ 59,
+ 61,
+ };
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) {
+ result[0] = '-';
+ i = 1;
+ }
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, firstDigitIndex, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent - charLength;
+ Arrays.fill(result,i,i+charLength,'0');
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <= 0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ Arrays.fill(result, i, i-decExponent, '0');
+ i -= decExponent;
+ }
+ System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[firstDigitIndex];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+ i += nDigits - 1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent + 1;
+ } else {
+ e = decExponent - 1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char) (e + '0');
+ } else if (e <= 99) {
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ } else {
+ result[i++] = (char) (e / 100 + '0');
+ e %= 100;
+ result[i++] = (char) (e / 10 + '0');
+ result[i++] = (char) (e % 10 + '0');
+ }
+ }
+ return i;
+ }
+
+ }
+
+ private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
+ new ThreadLocal<BinaryToASCIIBuffer>() {
+ @Override
+ protected BinaryToASCIIBuffer initialValue() {
+ return new BinaryToASCIIBuffer();
+ }
+ };
+
+ private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+ return threadLocalBinaryToASCIIBuffer.get();
+ }
+
+ /**
+ * A converter which can process an ASCII <code>String</code> representation
+ * of a single or double precision floating point value into a
+ * <code>float</code> or a <code>double</code>.
+ */
+ interface ASCIIToBinaryConverter {
+
+ double doubleValue();
+
+ float floatValue();
+
+ }
+
+ /**
+ * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
+ */
+ static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ private final double doubleVal;
+ private final float floatVal;
+
+ public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
+ this.doubleVal = doubleVal;
+ this.floatVal = floatVal;
+ }
+
+ @Override
+ public double doubleValue() {
+ return doubleVal;
+ }
+
+ @Override
+ public float floatValue() {
+ return floatVal;
+ }
+ }
+
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
+ static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
+ static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
+ static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
+
+ /**
+ * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
+ */
+ static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+
+ ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+ {
+ this.isNegative = negSign;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+ @Override
+ public double doubleValue() {
+ int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to a long integer.
+ //
+ // (special performance hack: start to do it using int)
+ int iValue = (int) digits[0] - (int) '0';
+ int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+ for (int i = 1; i < iDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ long lValue = (long) iValue;
+ for (int i = iDigits; i < kDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ int exp = decExponent - kDigits;
+ //
+ // lValue now contains a long integer with the value of
+ // the first kDigits digits of the number.
+ // dValue contains the (double) of the same.
+ //
+
+ if (nDigits <= MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here
+ //
+ if (exp == 0 || dValue == 0.0) {
+ return (isNegative) ? -dValue : dValue; // small floating integer
+ }
+ else if (exp >= 0) {
+ if (exp <= MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ double rValue = dValue * SMALL_10_POW[exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ int slop = MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply dValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ dValue *= SMALL_10_POW[slop];
+ double rValue = dValue * SMALL_10_POW[exp - slop];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ double rValue = dValue / SMALL_10_POW[-exp];
+ return (isNegative) ? -rValue : rValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ }
+
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ //
+ if (exp > 0) {
+ if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could overflow.
+ //
+ double t = dValue * BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ //
+ // It did overflow.
+ // Look more closely at the result.
+ // If the exponent is just one too large,
+ // then use the maximum finite as our estimate
+ // value. Else call the result infinity
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two larger than
+ // Double.MAX_VALUE ).
+ //
+ t = dValue / 2.0;
+ t *= BIG_10_POW[j];
+ if (Double.isInfinite(t)) {
+ return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 1; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ //
+ // The reason for the weird exp > 1 condition
+ // in the above loop was so that the last multiply
+ // would get unrolled. We handle it here.
+ // It could underflow.
+ //
+ double t = dValue * TINY_10_POW[j];
+ if (t == 0.0) {
+ //
+ // It did underflow.
+ // Look more closely at the result.
+ // If the exponent is just one too small,
+ // then use the minimum finite as our estimate
+ // value. Else call the result 0.0
+ // and punt it.
+ // ( I presume this could happen because
+ // rounding forces the result here to be
+ // an ULP or two less than
+ // Double.MIN_VALUE ).
+ //
+ t = dValue * 2.0;
+ t *= TINY_10_POW[j];
+ if (t == 0.0) {
+ return (isNegative) ? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ //
+ // dValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > MAX_NDIGITS) {
+ nDigits = MAX_NDIGITS + 1;
+ digits[MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = (int) (ieeeBits >>> EXP_SHIFT);
+ long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+ int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (63 - EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= DoubleConsts.EXP_BIAS;
+ int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -DoubleConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
+ }
+ return Double.longBitsToDouble(ieeeBits);
+ }
+
+ /**
+ * Takes a FloatingDecimal, which we presumably just scanned in,
+ * and finds out what its value is, as a float.
+ * This is distinct from doubleValue() to avoid the extremely
+ * unlikely case of a double rounding error, wherein the conversion
+ * to double has one rounding error, and the conversion of that double
+ * to a float has another rounding error, IN THE WRONG DIRECTION,
+ * ( because of the preference to a zero low-order bit ).
+ */
+ @Override
+ public float floatValue() {
+ int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+ //
+ // convert the lead kDigits to an integer.
+ //
+ int iValue = (int) digits[0] - (int) '0';
+ for (int i = 1; i < kDigits; i++) {
+ iValue = iValue * 10 + (int) digits[i] - (int) '0';
+ }
+ float fValue = (float) iValue;
+ int exp = decExponent - kDigits;
+ //
+ // iValue now contains an integer with the value of
+ // the first kDigits digits of the number.
+ // fValue contains the (float) of the same.
+ //
+
+ if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+ //
+ // possibly an easy case.
+ // We know that the digits can be represented
+ // exactly. And if the exponent isn't too outrageous,
+ // the whole thing can be done with one operation,
+ // thus one rounding error.
+ // Note that all our constructors trim all leading and
+ // trailing zeros, so simple values (including zero)
+ // will always end up here.
+ //
+ if (exp == 0 || fValue == 0.0f) {
+ return (isNegative) ? -fValue : fValue; // small floating integer
+ } else if (exp >= 0) {
+ if (exp <= SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer with one operation,
+ // thus one roundoff.
+ //
+ fValue *= SINGLE_SMALL_10_POW[exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+ if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+ //
+ // We can multiply fValue by 10^(slop)
+ // and it is still "small" and exact.
+ // Then we can multiply by 10^(exp-slop)
+ // with one rounding.
+ //
+ fValue *= SINGLE_SMALL_10_POW[slop];
+ fValue *= SINGLE_SMALL_10_POW[exp - slop];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a positive exp.
+ //
+ } else {
+ if (exp >= -SINGLE_MAX_SMALL_TEN) {
+ //
+ // Can get the answer in one division.
+ //
+ fValue /= SINGLE_SMALL_10_POW[-exp];
+ return (isNegative) ? -fValue : fValue;
+ }
+ //
+ // Else we have a hard case with a negative exp.
+ //
+ }
+ } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+ //
+ // In double-precision, this is an exact floating integer.
+ // So we can compute to double, then shorten to float
+ // with one round, and get the right answer.
+ //
+ // First, finish accumulating digits.
+ // Then convert that integer to a double, multiply
+ // by the appropriate power of ten, and convert to float.
+ //
+ long lValue = (long) iValue;
+ for (int i = kDigits; i < nDigits; i++) {
+ lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+ }
+ double dValue = (double) lValue;
+ exp = decExponent - nDigits;
+ dValue *= SMALL_10_POW[exp];
+ fValue = (float) dValue;
+ return (isNegative) ? -fValue : fValue;
+
+ }
+ //
+ // Harder cases:
+ // The sum of digits plus exponent is greater than
+ // what we think we can do with one error.
+ //
+ // Start by approximating the right answer by,
+ // naively, scaling by powers of 10.
+ // Scaling uses doubles to avoid overflow/underflow.
+ //
+ double dValue = fValue;
+ if (exp > 0) {
+ if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+ //
+ // Lets face it. This is going to be
+ // Infinity. Cut to the chase.
+ //
+ return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ }
+ if ((exp & 15) != 0) {
+ dValue *= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= BIG_10_POW[j];
+ }
+ }
+ }
+ } else if (exp < 0) {
+ exp = -exp;
+ if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+ //
+ // Lets face it. This is going to be
+ // zero. Cut to the chase.
+ //
+ return (isNegative) ? -0.0f : 0.0f;
+ }
+ if ((exp & 15) != 0) {
+ dValue /= SMALL_10_POW[exp & 15];
+ }
+ if ((exp >>= 4) != 0) {
+ int j;
+ for (j = 0; exp > 0; j++, exp >>= 1) {
+ if ((exp & 1) != 0) {
+ dValue *= TINY_10_POW[j];
+ }
+ }
+ }
+ }
+ fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
+
+ //
+ // fValue is now approximately the result.
+ // The hard part is adjusting it, by comparison
+ // with FDBigInteger arithmetic.
+ // Formulate the EXACT big-number result as
+ // bigD0 * 10^exp
+ //
+ if (nDigits > SINGLE_MAX_NDIGITS) {
+ nDigits = SINGLE_MAX_NDIGITS + 1;
+ digits[SINGLE_MAX_NDIGITS] = '1';
+ }
+ FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
+ exp = decExponent - nDigits;
+
+ int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
+ final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+ final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+ bigD0 = bigD0.multByPow52(D5, 0);
+ bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
+ FDBigInteger bigD = null;
+ int prevD2 = 0;
+
+ correctionLoop:
+ while (true) {
+ // here ieeeBits can't be NaN, Infinity or zero
+ int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
+ int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
+ if (binexp > 0) {
+ bigBbits |= SINGLE_FRACT_HOB;
+ } else { // Normalize denormalized numbers.
+ assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
+ int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
+ int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
+ bigBbits <<= shift;
+ binexp = 1 - shift;
+ }
+ binexp -= FloatConsts.EXP_BIAS;
+ int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
+ bigBbits >>>= lowOrderZeros;
+ final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
+ final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
+
+ //
+ // Scale bigD, bigB appropriately for
+ // big-integer operations.
+ // Naively, we multiply by powers of ten
+ // and powers of two. What we actually do
+ // is keep track of the powers of 5 and
+ // powers of 2 we would use, then factor out
+ // common divisors before doing the work.
+ //
+ int B2 = B5; // powers of 2 in bigB
+ int D2 = D5; // powers of 2 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if (bigIntExp >= 0) {
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if (binexp <= -FloatConsts.EXP_BIAS) {
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
+ hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
+ } else {
+ hulpbias = 1 + lowOrderZeros;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min(B2, Math.min(D2, Ulp2));
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+ if (bigD == null || prevD2 != D2) {
+ bigD = bigD0.leftShift(D2);
+ prevD2 = D2;
+ }
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ FDBigInteger diff;
+ int cmpResult;
+ boolean overvalue;
+ if ((cmpResult = bigB.cmp(bigD)) > 0) {
+ overvalue = true; // our candidate is too big.
+ diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+ if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
+ // candidate is a normalized exact power of 2 and
+ // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if (Ulp2 < 0) {
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff = diff.leftShift(1);
+ }
+ }
+ } else if (cmpResult < 0) {
+ overvalue = false; // our candidate is too small.
+ diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ cmpResult = diff.cmpPow52(B5, Ulp2);
+ if ((cmpResult) < 0) {
+ // difference is small.
+ // this is close enough
+ break correctionLoop;
+ } else if (cmpResult == 0) {
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ if ((ieeeBits & 1) != 0) { // half ties to even
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
+ if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
+ break correctionLoop; // oops. Fell off end of range.
+ }
+ continue; // try again.
+ }
+
+ }
+ if (isNegative) {
+ ieeeBits |= FloatConsts.SIGN_BIT_MASK;
+ }
+ return Float.intBitsToFloat(ieeeBits);
+ }
+
+
+ /**
+ * All the positive powers of 10 that can be
+ * represented exactly in double/float.
+ */
+ private static final double[] SMALL_10_POW = {
+ 1.0e0,
+ 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+ 1.0e21, 1.0e22
+ };
+
+ private static final float[] SINGLE_SMALL_10_POW = {
+ 1.0e0f,
+ 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+ 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+ };
+
+ private static final double[] BIG_10_POW = {
+ 1e16, 1e32, 1e64, 1e128, 1e256 };
+ private static final double[] TINY_10_POW = {
+ 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+ private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+ private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @return The converter.
+ */
+ public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+ return getBinaryToASCIIConverter(d, true);
+ }
+
+ /**
+ * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
+ * The returned object is a <code>ThreadLocal</code> variable of this class.
+ *
+ * @param d The double precision value to convert.
+ * @param isCompatibleFormat
+ * @return The converter.
+ */
+ static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+ long dBits = Double.doubleToRawLongBits(d);
+ boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+ long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+ int binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(63-EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 64-leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= FRACT_HOB;
+ nSignificantBits = EXP_SHIFT+1;
+ }
+ binExp -= DoubleConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+ return buf;
+ }
+
+ private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+ int fBits = Float.floatToRawIntBits( f );
+ boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+ int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+ int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+ // Discover obvious special cases of NaN and Infinity.
+ if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+ if ( fractBits == 0L ){
+ return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+ } else {
+ return B2AC_NOT_A_NUMBER;
+ }
+ }
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ int nSignificantBits;
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+ }
+ int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+ int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+ fractBits <<= shift;
+ binExp = 1 - shift;
+ nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
+ } else {
+ fractBits |= SINGLE_FRACT_HOB;
+ nSignificantBits = SINGLE_EXP_SHIFT+1;
+ }
+ binExp -= FloatConsts.EXP_BIAS;
+ BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+ buf.setSign(isNegative);
+ // call the routine that actually does all the hard work.
+ buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+ return buf;
+ }
+
+ @SuppressWarnings("fallthrough")
+ static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int len = in.length();
+ if ( len == 0 ) {
+ throw new NumberFormatException("empty String");
+ }
+ int i = 0;
+ switch (in.charAt(i)){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+ c = in.charAt(i);
+ if(c == 'N') { // Check for NaN
+ if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+ return A2BC_NOT_A_NUMBER;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if(c == 'I') { // Check for Infinity strings
+ if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+ return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ }
+ // something went wrong, throw exception
+ break parseNumber;
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (len > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) { // possible hex string
+ return parseHexString(in);
+ }
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ len ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+
+ skipLeadingZerosLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c == '0') {
+ nLeadZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break skipLeadingZerosLoop;
+ }
+ i++;
+ }
+ digitLoop:
+ while (i < len) {
+ c = in.charAt(i);
+ if (c >= '1' && c <= '9') {
+ digits[nDigits++] = c;
+ nTrailZero = 0;
+ } else if (c == '0') {
+ digits[nDigits++] = c;
+ nTrailZero++;
+ } else if (c == '.') {
+ if (decSeen) {
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if (signSeen) {
+ decPt -= 1;
+ }
+ decSeen = true;
+ } else {
+ break digitLoop;
+ }
+ i++;
+ }
+ nDigits -=nTrailZero;
+ //
+ // At this point, we've scanned all the digits and decimal
+ // point we're going to see. Trim off leading and trailing
+ // zeros, which will just confuse us later, and adjust
+ // our initial decimal exponent accordingly.
+ // To review:
+ // we have seen i total characters.
+ // nLeadZero of them were zeros before any other digits.
+ // nTrailZero of them were zeros after any other digits.
+ // if ( decSeen ), then a . was seen after decPt characters
+ // ( including leading zeros which have been discarded )
+ // nDigits characters were neither lead nor trailing
+ // zeros, nor point
+ //
+ //
+ // special hack: if we saw no non-zero digits, then the
+ // answer is zero!
+ // Unfortunately, we feel honor-bound to keep parsing!
+ //
+ boolean isZero = (nDigits == 0);
+ if ( isZero && nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+ //
+ // Our initial exponent is decPt, adjusted by the number of
+ // discarded zeros. Or, if there was no decPt,
+ // then its just nDigits adjusted by discarded trailing zeros.
+ //
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits + nTrailZero;
+ }
+
+ //
+ // Look for 'e' or 'E' and an optionally signed integer.
+ //
+ if ( (i < len) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < len ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ c = in.charAt(i++);
+ if(c>='0' && c<='9') {
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ } else {
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
+ if (expOverflow || (expVal > expLimit)) {
+ // There is still a chance that the exponent will be safe to
+ // use: if it would eventually decrease due to a negative
+ // decExp, and that number is below the limit. We check for
+ // that here.
+ if (!expOverflow && (expSign == 1 && decExp < 0)
+ && (expVal + decExp) < expLimit) {
+ // Cannot overflow: adding a positive and negative number.
+ decExp += expVal;
+ } else {
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2
+ // billion.)
+ //
+ decExp = expSign * expLimit;
+ }
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt ) {
+ break parseNumber; // certainly bad
+ }
+ }
+ //
+ // We parsed everything we could.
+ // If there are leftovers, then this is not good input!
+ //
+ if ( i < len &&
+ ((i != len - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+ if(isZero) {
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ private static class HexFloatPattern {
+ /**
+ * Grammar is compatible with hexadecimal floating-point constants
+ * described in section 6.4.4.2 of the C99 specification.
+ */
+ private static final Pattern VALUE = Pattern.compile(
+ //1 234 56 7 8 9
+ "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+ );
+ }
+
+ /**
+ * Converts string s to a suitable floating decimal; uses the
+ * double constructor and sets the roundDir variable appropriately
+ * in case the value is later converted to a float.
+ *
+ * @param s The <code>String</code> to parse.
+ */
+ static ASCIIToBinaryConverter parseHexString(String s) {
+ // Verify string is a member of the hexadecimal floating-point
+ // string language.
+ Matcher m = HexFloatPattern.VALUE.matcher(s);
+ boolean validInput = m.matches();
+ if (!validInput) {
+ // Input does not match pattern
+ throw new NumberFormatException("For input string: \"" + s + "\"");
+ } else { // validInput
+ //
+ // We must isolate the sign, significand, and exponent
+ // fields. The sign value is straightforward. Since
+ // floating-point numbers are stored with a normalized
+ // representation, the significand and exponent are
+ // interrelated.
+ //
+ // After extracting the sign, we normalized the
+ // significand as a hexadecimal value, calculating an
+ // exponent adjust for any shifts made during
+ // normalization. If the significand is zero, the
+ // exponent doesn't need to be examined since the output
+ // will be zero.
+ //
+ // Next the exponent in the input string is extracted.
+ // Afterwards, the significand is normalized as a *binary*
+ // value and the input value's normalized exponent can be
+ // computed. The significand bits are copied into a
+ // double significand; if the string has more logical bits
+ // than can fit in a double, the extra bits affect the
+ // round and sticky bits which are used to round the final
+ // value.
+ //
+ // Extract significand sign
+ String group1 = m.group(1);
+ boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+ // Extract Significand magnitude
+ //
+ // Based on the form of the significand, calculate how the
+ // binary exponent needs to be adjusted to create a
+ // normalized//hexadecimal* floating-point number; that
+ // is, a number where there is one nonzero hex digit to
+ // the left of the (hexa)decimal point. Since we are
+ // adjusting a binary, not hexadecimal exponent, the
+ // exponent is adjusted by a multiple of 4.
+ //
+ // There are a number of significand scenarios to consider;
+ // letters are used in indicate nonzero digits:
+ //
+ // 1. 000xxxx => x.xxx normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 2. 000xxx.yyyy => x.xxyyyy normalized
+ // increase exponent by (number of x's - 1)*4
+ //
+ // 3. .000yyy => y.yy normalized
+ // decrease exponent by (number of zeros + 1)*4
+ //
+ // 4. 000.00000yyy => y.yy normalized
+ // decrease exponent by (number of zeros to right of point + 1)*4
+ //
+ // If the significand is exactly zero, return a properly
+ // signed zero.
+ //
+
+ String significandString = null;
+ int signifLength = 0;
+ int exponentAdjust = 0;
+ {
+ int leftDigits = 0; // number of meaningful digits to
+ // left of "decimal" point
+ // (leading zeros stripped)
+ int rightDigits = 0; // number of digits to right of
+ // "decimal" point; leading zeros
+ // must always be accounted for
+ //
+ // The significand is made up of either
+ //
+ // 1. group 4 entirely (integer portion only)
+ //
+ // OR
+ //
+ // 2. the fractional portion from group 7 plus any
+ // (optional) integer portions from group 6.
+ //
+ String group4;
+ if ((group4 = m.group(4)) != null) { // Integer-only significand
+ // Leading zeros never matter on the integer portion
+ significandString = stripLeadingZeros(group4);
+ leftDigits = significandString.length();
+ } else {
+ // Group 6 is the optional integer; leading zeros
+ // never matter on the integer portion
+ String group6 = stripLeadingZeros(m.group(6));
+ leftDigits = group6.length();
+
+ // fraction
+ String group7 = m.group(7);
+ rightDigits = group7.length();
+
+ // Turn "integer.fraction" into "integer"+"fraction"
+ significandString =
+ ((group6 == null) ? "" : group6) + // is the null
+ // check necessary?
+ group7;
+ }
+
+ significandString = stripLeadingZeros(significandString);
+ signifLength = significandString.length();
+
+ //
+ // Adjust exponent as described above
+ //
+ if (leftDigits >= 1) { // Cases 1 and 2
+ exponentAdjust = 4 * (leftDigits - 1);
+ } else { // Cases 3 and 4
+ exponentAdjust = -4 * (rightDigits - signifLength + 1);
+ }
+
+ // If the significand is zero, the exponent doesn't
+ // matter; return a properly signed zero.
+
+ if (signifLength == 0) { // Only zeros in input
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ }
+ }
+
+ // Extract Exponent
+ //
+ // Use an int to read in the exponent value; this should
+ // provide more than sufficient range for non-contrived
+ // inputs. If reading the exponent in as an int does
+ // overflow, examine the sign of the exponent and
+ // significand to determine what to do.
+ //
+ String group8 = m.group(8);
+ boolean positiveExponent = (group8 == null) || group8.equals("+");
+ long unsignedRawExponent;
+ try {
+ unsignedRawExponent = Integer.parseInt(m.group(9));
+ }
+ catch (NumberFormatException e) {
+ // At this point, we know the exponent is
+ // syntactically well-formed as a sequence of
+ // digits. Therefore, if an NumberFormatException
+ // is thrown, it must be due to overflowing int's
+ // range. Also, at this point, we have already
+ // checked for a zero significand. Thus the signs
+ // of the exponent and significand determine the
+ // final result:
+ //
+ // significand
+ // + -
+ // exponent + +infinity -infinity
+ // - +0.0 -0.0
+ return isNegative ?
+ (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+ : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
+
+ }
+
+ long rawExponent =
+ (positiveExponent ? 1L : -1L) * // exponent sign
+ unsignedRawExponent; // exponent magnitude
+
+ // Calculate partially adjusted exponent
+ long exponent = rawExponent + exponentAdjust;
+
+ // Starting copying non-zero bits into proper position in
+ // a long; copy explicit bit too; this will be masked
+ // later for normal values.
+
+ boolean round = false;
+ boolean sticky = false;
+ int nextShift = 0;
+ long significand = 0L;
+ // First iteration is different, since we only copy
+ // from the leading significand bit; one more exponent
+ // adjust will be needed...
+
+ // IMPORTANT: make leadingDigit a long to avoid
+ // surprising shift semantics!
+ long leadingDigit = getHexDigit(significandString, 0);
+
+ //
+ // Left shift the leading digit (53 - (bit position of
+ // leading 1 in digit)); this sets the top bit of the
+ // significand to 1. The nextShift value is adjusted
+ // to take into account the number of bit positions of
+ // the leadingDigit actually used. Finally, the
+ // exponent is adjusted to normalize the significand
+ // as a binary value, not just a hex value.
+ //
+ if (leadingDigit == 1) {
+ significand |= leadingDigit << 52;
+ nextShift = 52 - 4;
+ // exponent += 0
+ } else if (leadingDigit <= 3) { // [2, 3]
+ significand |= leadingDigit << 51;
+ nextShift = 52 - 5;
+ exponent += 1;
+ } else if (leadingDigit <= 7) { // [4, 7]
+ significand |= leadingDigit << 50;
+ nextShift = 52 - 6;
+ exponent += 2;
+ } else if (leadingDigit <= 15) { // [8, f]
+ significand |= leadingDigit << 49;
+ nextShift = 52 - 7;
+ exponent += 3;
+ } else {
+ throw new AssertionError("Result from digit conversion too large!");
+ }
+ // The preceding if-else could be replaced by a single
+ // code block based on the high-order bit set in
+ // leadingDigit. Given leadingOnePosition,
+
+ // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+ // nextShift = 52 - (3 + leadingOnePosition);
+ // exponent += (leadingOnePosition-1);
+
+ //
+ // Now the exponent variable is equal to the normalized
+ // binary exponent. Code below will make representation
+ // adjustments if the exponent is incremented after
+ // rounding (includes overflows to infinity) or if the
+ // result is subnormal.
+ //
+
+ // Copy digit into significand until the significand can't
+ // hold another full hex digit or there are no more input
+ // hex digits.
+ int i = 0;
+ for (i = 1;
+ i < signifLength && nextShift >= 0;
+ i++) {
+ long currentDigit = getHexDigit(significandString, i);
+ significand |= (currentDigit << nextShift);
+ nextShift -= 4;
+ }
+
+ // After the above loop, the bulk of the string is copied.
+ // Now, we must copy any partial hex digits into the
+ // significand AND compute the round bit and start computing
+ // sticky bit.
+
+ if (i < signifLength) { // at least one hex input digit exists
+ long currentDigit = getHexDigit(significandString, i);
+
+ // from nextShift, figure out how many bits need
+ // to be copied, if any
+ switch (nextShift) { // must be negative
+ case -1:
+ // three bits need to be copied in; can
+ // set round bit
+ significand |= ((currentDigit & 0xEL) >> 1);
+ round = (currentDigit & 0x1L) != 0L;
+ break;
+
+ case -2:
+ // two bits need to be copied in; can
+ // set round and start sticky
+ significand |= ((currentDigit & 0xCL) >> 2);
+ round = (currentDigit & 0x2L) != 0L;
+ sticky = (currentDigit & 0x1L) != 0;
+ break;
+
+ case -3:
+ // one bit needs to be copied in
+ significand |= ((currentDigit & 0x8L) >> 3);
+ // Now set round and start sticky, if possible
+ round = (currentDigit & 0x4L) != 0L;
+ sticky = (currentDigit & 0x3L) != 0;
+ break;
+
+ case -4:
+ // all bits copied into significand; set
+ // round and start sticky
+ round = ((currentDigit & 0x8L) != 0); // is top bit set?
+ // nonzeros in three low order bits?
+ sticky = (currentDigit & 0x7L) != 0;
+ break;
+
+ default:
+ throw new AssertionError("Unexpected shift distance remainder.");
+ // break;
+ }
+
+ // Round is set; sticky might be set.
+
+ // For the sticky bit, it suffices to check the
+ // current digit and test for any nonzero digits in
+ // the remaining unprocessed input.
+ i++;
+ while (i < signifLength && !sticky) {
+ currentDigit = getHexDigit(significandString, i);
+ sticky = sticky || (currentDigit != 0);
+ i++;
+ }
+
+ }
+ // else all of string was seen, round and sticky are
+ // correct as false.
+
+ // Float calculations
+ int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
+ if (exponent >= FloatConsts.MIN_EXPONENT) {
+ if (exponent > FloatConsts.MAX_EXPONENT) {
+ // Float.POSITIVE_INFINITY
+ floatBits |= FloatConsts.EXP_BIT_MASK;
+ } else {
+ int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
+ }
+ } else {
+ if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
+ // 0
+ } else {
+ // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
+ int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
+ assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
+ assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
+ boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
+ int iValue = (int) (significand >>> threshShift);
+ if ((iValue & 3) != 1 || floatSticky) {
+ iValue++;
+ }
+ floatBits |= iValue >> 1;
+ }
+ }
+ float fValue = Float.intBitsToFloat(floatBits);
+
+ // Check for overflow and update exponent accordingly.
+ if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
+ // overflow to properly signed infinity
+ return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+ } else { // Finite return value
+ if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+ exponent >= DoubleConsts.MIN_EXPONENT) {
+
+ // The result returned in this block cannot be a
+ // zero or subnormal; however after the
+ // significand is adjusted from rounding, we could
+ // still overflow in infinity.
+
+ // AND exponent bits into significand; if the
+ // significand is incremented and overflows from
+ // rounding, this combination will update the
+ // exponent correctly, even in the case of
+ // Double.MAX_VALUE overflowing to infinity.
+
+ significand = ((( exponent +
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+ } else { // Subnormal or zero
+ // (exponent < DoubleConsts.MIN_EXPONENT)
+
+ if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+ // No way to round back to nonzero value
+ // regardless of significand if the exponent is
+ // less than -1075.
+ return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+ } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+ //
+ // Find bit position to round to; recompute
+ // round and sticky bits, and shift
+ // significand right appropriately.
+ //
+
+ sticky = sticky || round;
+ round = false;
+
+ // Number of bits of significand to preserve is
+ // exponent - abs_min_exp +1
+ // check:
+ // -1075 +1074 + 1 = 0
+ // -1023 +1074 + 1 = 52
+
+ int bitsDiscarded = 53 -
+ ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+ assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+ // What to do here:
+ // First, isolate the new round bit
+ round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+ if (bitsDiscarded > 1) {
+ // create mask to update sticky bits; low
+ // order bitsDiscarded bits should be 1
+ long mask = ~((~0L) << (bitsDiscarded - 1));
+ sticky = sticky || ((significand & mask) != 0L);
+ }
+
+ // Now, discard the bits
+ significand = significand >> bitsDiscarded;
+
+ significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+ (long) DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+ }
+ }
+
+ // The significand variable now contains the currently
+ // appropriate exponent bits too.
+
+ //
+ // Determine if significand should be incremented;
+ // making this determination depends on the least
+ // significant bit and the round and sticky bits.
+ //
+ // Round to nearest even rounding table, adapted from
+ // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+ // The digit to the left of the "decimal" point is the
+ // least significant bit, the digits to the right of
+ // the point are the round and sticky bits
+ //
+ // Number Round(x)
+ // x0.00 x0.
+ // x0.01 x0.
+ // x0.10 x0.
+ // x0.11 x1. = x0. +1
+ // x1.00 x1.
+ // x1.01 x1.
+ // x1.10 x1. + 1
+ // x1.11 x1. + 1
+ //
+ boolean leastZero = ((significand & 1L) == 0L);
+ if ((leastZero && round && sticky) ||
+ ((!leastZero) && round)) {
+ significand++;
+ }
+
+ double value = isNegative ?
+ Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+ Double.longBitsToDouble(significand );
+
+ return new PreparedASCIIToBinaryBuffer(value, fValue);
+ }
+ }
+ }
+
+ /**
+ * Returns <code>s</code> with any leading zeros removed.
+ */
+ static String stripLeadingZeros(String s) {
+// return s.replaceFirst("^0+", "");
+ if(!s.isEmpty() && s.charAt(0)=='0') {
+ for(int i=1; i<s.length(); i++) {
+ if(s.charAt(i)!='0') {
+ return s.substring(i);
+ }
+ }
+ return "";
+ }
+ return s;
+ }
+
+ /**
+ * Extracts a hexadecimal digit from position <code>position</code>
+ * of string <code>s</code>.
+ */
+ static int getHexDigit(String s, int position) {
+ int value = Character.digit(s.charAt(position), 16);
+ if (value <= -1 || value >= 16) {
+ throw new AssertionError("Unexpected failure of digit conversion of " +
+ s.charAt(position));
+ }
+ return value;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.math;
+
+import java.util.Arrays;
+
+public class FormattedFloatingDecimal{
+
+ public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
+
+
+ public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+ FloatingDecimal.BinaryToASCIIConverter fdConverter =
+ FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+ return new FormattedFloatingDecimal(precision,form, fdConverter);
+ }
+
+ private int decExponentRounded;
+ private char[] mantissa;
+ private char[] exponent;
+
+ private static final ThreadLocal<Object> threadLocalCharBuffer =
+ new ThreadLocal<Object>() {
+ @Override
+ protected Object initialValue() {
+ return new char[20];
+ }
+ };
+
+ private static char[] getBuffer(){
+ return (char[]) threadLocalCharBuffer.get();
+ }
+
+ private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+ if (fdConverter.isExceptional()) {
+ this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+ this.exponent = null;
+ return;
+ }
+ char[] digits = getBuffer();
+ int nDigits = fdConverter.getDigits(digits);
+ int decExp = fdConverter.getDecimalExponent();
+ int exp;
+ boolean isNegative = fdConverter.isNegative();
+ switch (form) {
+ case COMPATIBLE:
+ exp = decExp;
+ this.decExponentRounded = exp;
+ fillCompatible(precision, digits, nDigits, exp, isNegative);
+ break;
+ case DECIMAL_FLOAT:
+ exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+ fillDecimal(precision, digits, nDigits, exp, isNegative);
+ this.decExponentRounded = exp;
+ break;
+ case SCIENTIFIC:
+ exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+ fillScientific(precision, digits, nDigits, exp, isNegative);
+ this.decExponentRounded = exp;
+ break;
+ case GENERAL:
+ exp = applyPrecision(decExp, digits, nDigits, precision);
+ // adjust precision to be the number of digits to right of decimal
+ // the real exponent to be output is actually exp - 1, not exp
+ if (exp - 1 < -4 || exp - 1 >= precision) {
+ // form = Form.SCIENTIFIC;
+ precision--;
+ fillScientific(precision, digits, nDigits, exp, isNegative);
+ } else {
+ // form = Form.DECIMAL_FLOAT;
+ precision = precision - exp;
+ fillDecimal(precision, digits, nDigits, exp, isNegative);
+ }
+ this.decExponentRounded = exp;
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ // returns the exponent after rounding has been done by applyPrecision
+ public int getExponentRounded() {
+ return decExponentRounded - 1;
+ }
+
+ public char[] getMantissa(){
+ return mantissa;
+ }
+
+ public char[] getExponent(){
+ return exponent;
+ }
+
+ /**
+ * Returns new decExp in case of overflow.
+ */
+ private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+ if (prec >= nDigits || prec < 0) {
+ // no rounding necessary
+ return decExp;
+ }
+ if (prec == 0) {
+ // only one digit (0 or 1) is returned because the precision
+ // excludes all significant digits
+ if (digits[0] >= '5') {
+ digits[0] = '1';
+ Arrays.fill(digits, 1, nDigits, '0');
+ return decExp + 1;
+ } else {
+ Arrays.fill(digits, 0, nDigits, '0');
+ return decExp;
+ }
+ }
+ int q = digits[prec];
+ if (q >= '5') {
+ int i = prec;
+ q = digits[--i];
+ if ( q == '9' ) {
+ while ( q == '9' && i > 0 ){
+ q = digits[--i];
+ }
+ if ( q == '9' ){
+ // carryout! High-order 1, rest 0s, larger exp.
+ digits[0] = '1';
+ Arrays.fill(digits, 1, nDigits, '0');
+ return decExp+1;
+ }
+ }
+ digits[i] = (char)(q + 1);
+ Arrays.fill(digits, i+1, nDigits, '0');
+ } else {
+ Arrays.fill(digits, prec, nDigits, '0');
+ }
+ return decExp;
+ }
+
+ /**
+ * Fills mantissa and exponent char arrays for compatible format.
+ */
+ private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ if (exp > 0 && exp < 8) {
+ // print digits.digits.
+ if (nDigits < exp) {
+ int extraZeros = exp - nDigits;
+ mantissa = create(isNegative, nDigits + extraZeros + 2);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+ mantissa[startIndex + nDigits + extraZeros] = '.';
+ mantissa[startIndex + nDigits + extraZeros+1] = '0';
+ } else if (exp < nDigits) {
+ int t = Math.min(nDigits - exp, precision);
+ mantissa = create(isNegative, exp + 1 + t);
+ System.arraycopy(digits, 0, mantissa, startIndex, exp);
+ mantissa[startIndex + exp ] = '.';
+ System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+ } else { // exp == digits.length
+ mantissa = create(isNegative, nDigits + 2);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ mantissa[startIndex + nDigits ] = '.';
+ mantissa[startIndex + nDigits +1] = '0';
+ }
+ } else if (exp <= 0 && exp > -3) {
+ int zeros = Math.max(0, Math.min(-exp, precision));
+ int t = Math.max(0, Math.min(nDigits, precision + exp));
+ // write '0' s before the significant digits
+ if (zeros > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex+1] = '.';
+ Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+ if (t > 0) {
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+ }
+ } else if (t > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex + 1] = '.';
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+ } else {
+ this.mantissa = create(isNegative, 1);
+ this.mantissa[startIndex] = '0';
+ }
+ } else {
+ if (nDigits > 1) {
+ mantissa = create(isNegative, nDigits + 1);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
+ } else {
+ mantissa = create(isNegative, 3);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ mantissa[startIndex + 2] = '0';
+ }
+ int e, expStartIntex;
+ boolean isNegExp = (exp <= 0);
+ if (isNegExp) {
+ e = -exp + 1;
+ expStartIntex = 1;
+ } else {
+ e = exp - 1;
+ expStartIntex = 0;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ exponent = create(isNegExp,1);
+ exponent[expStartIntex] = (char) (e + '0');
+ } else if (e <= 99) {
+ exponent = create(isNegExp,2);
+ exponent[expStartIntex] = (char) (e / 10 + '0');
+ exponent[expStartIntex+1] = (char) (e % 10 + '0');
+ } else {
+ exponent = create(isNegExp,3);
+ exponent[expStartIntex] = (char) (e / 100 + '0');
+ e %= 100;
+ exponent[expStartIntex+1] = (char) (e / 10 + '0');
+ exponent[expStartIntex+2] = (char) (e % 10 + '0');
+ }
+ }
+ }
+
+ private static char[] create(boolean isNegative, int size) {
+ if(isNegative) {
+ char[] r = new char[size +1];
+ r[0] = '-';
+ return r;
+ } else {
+ return new char[size];
+ }
+ }
+
+ /*
+ * Fills mantissa char arrays for DECIMAL_FLOAT format.
+ * Exponent should be equal to null.
+ */
+ private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ if (exp > 0) {
+ // print digits.digits.
+ if (nDigits < exp) {
+ mantissa = create(isNegative,exp);
+ System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+ Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+ // Do not append ".0" for formatted floats since the user
+ // may request that it be omitted. It is added as necessary
+ // by the Formatter.
+ } else {
+ int t = Math.min(nDigits - exp, precision);
+ mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+ System.arraycopy(digits, 0, mantissa, startIndex, exp);
+ // Do not append ".0" for formatted floats since the user
+ // may request that it be omitted. It is added as necessary
+ // by the Formatter.
+ if (t > 0) {
+ mantissa[startIndex + exp] = '.';
+ System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
+ }
+ }
+ } else if (exp <= 0) {
+ int zeros = Math.max(0, Math.min(-exp, precision));
+ int t = Math.max(0, Math.min(nDigits, precision + exp));
+ // write '0' s before the significant digits
+ if (zeros > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex+1] = '.';
+ Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+ if (t > 0) {
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
+ }
+ } else if (t > 0) {
+ mantissa = create(isNegative, zeros + 2 + t);
+ mantissa[startIndex] = '0';
+ mantissa[startIndex + 1] = '.';
+ // copy only when significant digits are within the precision
+ System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
+ } else {
+ this.mantissa = create(isNegative, 1);
+ this.mantissa[startIndex] = '0';
+ }
+ }
+ }
+
+ /**
+ * Fills mantissa and exponent char arrays for SCIENTIFIC format.
+ */
+ private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+ int startIndex = isNegative ? 1 : 0;
+ int t = Math.max(0, Math.min(nDigits - 1, precision));
+ if (t > 0) {
+ mantissa = create(isNegative, t + 2);
+ mantissa[startIndex] = digits[0];
+ mantissa[startIndex + 1] = '.';
+ System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+ } else {
+ mantissa = create(isNegative, 1);
+ mantissa[startIndex] = digits[0];
+ }
+ char expSign;
+ int e;
+ if (exp <= 0) {
+ expSign = '-';
+ e = -exp + 1;
+ } else {
+ expSign = '+' ;
+ e = exp - 1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ exponent = new char[] { expSign,
+ '0', (char) (e + '0') };
+ } else if (e <= 99) {
+ exponent = new char[] { expSign,
+ (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+ } else {
+ char hiExpChar = (char) (e / 100 + '0');
+ e %= 100;
+ exponent = new char[] { expSign,
+ hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/CleanerImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,788 @@
+/*
+ * 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 jdk.internal.misc;
+
+import java.lang.ref.Cleaner;
+import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Objects;
+import java.util.concurrent.ThreadFactory;
+import java.util.function.Function;
+
+import sun.misc.InnocuousThread;
+
+/**
+ * CleanerImpl manages a set of object references and corresponding cleaning actions.
+ * CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}.
+ */
+public final class CleanerImpl implements Runnable {
+
+ /**
+ * An object to access the CleanerImpl from a Cleaner; set by Cleaner init.
+ */
+ private static Function<Cleaner, CleanerImpl> cleanerImplAccess = null;
+
+ /**
+ * Heads of a CleanableList for each reference type.
+ */
+ final PhantomCleanable<?> phantomCleanableList;
+
+ final WeakCleanable<?> weakCleanableList;
+
+ final SoftCleanable<?> softCleanableList;
+
+ // The ReferenceQueue of pending cleaning actions
+ final ReferenceQueue<Object> queue;
+
+ /**
+ * Called by Cleaner static initialization to provide the function
+ * to map from Cleaner to CleanerImpl.
+ * @param access a function to map from Cleaner to CleanerImpl
+ */
+ public static void setCleanerImplAccess(Function<Cleaner, CleanerImpl> access) {
+ if (cleanerImplAccess == null) {
+ cleanerImplAccess = access;
+ }
+ }
+
+ /**
+ * Called to get the CleanerImpl for a Cleaner.
+ * @param cleaner the cleaner
+ * @return the corresponding CleanerImpl
+ */
+ private static CleanerImpl getCleanerImpl(Cleaner cleaner) {
+ return cleanerImplAccess.apply(cleaner);
+ }
+
+ /**
+ * Constructor for CleanerImpl.
+ */
+ public CleanerImpl() {
+ queue = new ReferenceQueue<>();
+ phantomCleanableList = new PhantomCleanableRef(this);
+ weakCleanableList = new WeakCleanableRef(this);
+ softCleanableList = new SoftCleanableRef(this);
+ }
+
+ /**
+ * Starts the Cleaner implementation.
+ * When started waits for Cleanables to be queued.
+ * @param service the cleaner
+ * @param threadFactory the thread factory
+ */
+ public void start(Cleaner service, ThreadFactory threadFactory) {
+ // schedule a nop cleaning action for the service, so the associated thread
+ // will continue to run at least until the service is reclaimable.
+ new PhantomCleanableRef(service, service, () -> {});
+
+ if (threadFactory == null) {
+ threadFactory = CleanerImpl.InnocuousThreadFactory.factory();
+ }
+
+ // now that there's at least one cleaning action, for the service,
+ // we can start the associated thread, which runs until
+ // all cleaning actions have been run.
+ Thread thread = threadFactory.newThread(this);
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ /**
+ * Process queued Cleanables as long as the cleanable lists are not empty.
+ * A Cleanable is in one of the lists for each Object and for the Cleaner
+ * itself.
+ * Terminates when the Cleaner is no longer reachable and
+ * has been cleaned and there are no more Cleanable instances
+ * for which the object is reachable.
+ * <p>
+ * If the thread is a ManagedLocalsThread, the threadlocals
+ * are erased before each cleanup
+ */
+ public void run() {
+ Thread t = Thread.currentThread();
+ InnocuousThread mlThread = (t instanceof InnocuousThread)
+ ? (InnocuousThread) t
+ : null;
+ while (!phantomCleanableList.isListEmpty() ||
+ !weakCleanableList.isListEmpty() ||
+ !softCleanableList.isListEmpty()) {
+ if (mlThread != null) {
+ // Clear the thread locals
+ mlThread.eraseThreadLocals();
+ }
+ try {
+ // Wait for a Ref, with a timeout to avoid getting hung
+ // due to a race with clear/clean
+ Cleanable ref = (Cleanable) queue.remove(60 * 1000L);
+ if (ref != null) {
+ ref.clean();
+ }
+ } catch (InterruptedException i) {
+ continue; // ignore the interruption
+ } catch (Throwable e) {
+ // ignore exceptions from the cleanup action
+ }
+ }
+ }
+
+ /**
+ * PhantomCleanable subclasses efficiently encapsulate cleanup state and
+ * the cleaning action.
+ * Subclasses implement the abstract {@link #performCleanup()} method
+ * to provide the cleaning action.
+ * When constructed, the object reference and the {@link Cleanable Cleanable}
+ * are registered with the {@link Cleaner}.
+ * The Cleaner invokes {@link Cleaner.Cleanable#clean() clean} after the
+ * referent becomes phantom reachable.
+ */
+ public static abstract class PhantomCleanable<T> extends PhantomReference<T>
+ implements Cleaner.Cleanable {
+
+ /**
+ * Links to previous and next in a doubly-linked list.
+ */
+ PhantomCleanable<?> prev = this, next = this;
+
+ /**
+ * The CleanerImpl for this Cleanable.
+ */
+ private final CleanerImpl cleanerImpl;
+
+ /**
+ * Constructs new {@code PhantomCleanable} with
+ * {@code non-null referent} and {@code non-null cleaner}.
+ * The {@code cleaner} is not retained; it is only used to
+ * register the newly constructed {@link Cleaner.Cleanable Cleanable}.
+ *
+ * @param referent the referent to track
+ * @param cleaner the {@code Cleaner} to register with
+ */
+ public PhantomCleanable(T referent, Cleaner cleaner) {
+ super(Objects.requireNonNull(referent), getCleanerImpl(cleaner).queue);
+ this.cleanerImpl = getCleanerImpl(cleaner);
+ insert();
+
+ // TODO: Replace getClass() with ReachabilityFence when it is available
+ cleaner.getClass();
+ referent.getClass();
+ }
+
+ /**
+ * Construct a new root of the list; not inserted.
+ */
+ PhantomCleanable(CleanerImpl cleanerImpl) {
+ super(null, null);
+ this.cleanerImpl = cleanerImpl;
+ }
+
+ /**
+ * Insert this PhantomCleanable after the list head.
+ */
+ private void insert() {
+ final PhantomCleanable<?> list = cleanerImpl.phantomCleanableList;
+ synchronized (list) {
+ prev = list;
+ next = list.next;
+ next.prev = this;
+ list.next = this;
+ }
+ }
+
+ /**
+ * Remove this PhantomCleanable from the list.
+ *
+ * @return true if Cleanable was removed or false if not because
+ * it had already been removed before
+ */
+ private boolean remove() {
+ PhantomCleanable<?> list = cleanerImpl.phantomCleanableList;
+ synchronized (list) {
+ if (next != this) {
+ next.prev = prev;
+ prev.next = next;
+ prev = this;
+ next = this;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the list's next reference refers to itself.
+ *
+ * @return true if the list is empty
+ */
+ boolean isListEmpty() {
+ PhantomCleanable<?> list = cleanerImpl.phantomCleanableList;
+ synchronized (list) {
+ return list == list.next;
+ }
+ }
+
+ /**
+ * Unregister this PhantomCleanable and invoke {@link #performCleanup()},
+ * ensuring at-most-once semantics.
+ */
+ @Override
+ public final void clean() {
+ if (remove()) {
+ super.clear();
+ performCleanup();
+ }
+ }
+
+ /**
+ * Unregister this PhantomCleanable and clear the reference.
+ * Due to inherent concurrency, {@link #performCleanup()} may still be invoked.
+ */
+ @Override
+ public void clear() {
+ if (remove()) {
+ super.clear();
+ }
+ }
+
+ /**
+ * The {@code performCleanup} abstract method is overridden
+ * to implement the cleaning logic.
+ * The {@code performCleanup} method should not be called except
+ * by the {@link #clean} method which ensures at most once semantics.
+ */
+ protected abstract void performCleanup();
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean isEnqueued() {
+ throw new UnsupportedOperationException("isEnqueued");
+ }
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean enqueue() {
+ throw new UnsupportedOperationException("enqueue");
+ }
+ }
+
+ /**
+ * WeakCleanable subclasses efficiently encapsulate cleanup state and
+ * the cleaning action.
+ * Subclasses implement the abstract {@link #performCleanup()} method
+ * to provide the cleaning action.
+ * When constructed, the object reference and the {@link Cleanable Cleanable}
+ * are registered with the {@link Cleaner}.
+ * The Cleaner invokes {@link Cleaner.Cleanable#clean() clean} after the
+ * referent becomes weakly reachable.
+ */
+ public static abstract class WeakCleanable<T> extends WeakReference<T>
+ implements Cleaner.Cleanable {
+
+ /**
+ * Links to previous and next in a doubly-linked list.
+ */
+ WeakCleanable<?> prev = this, next = this;
+
+ /**
+ * The CleanerImpl for this Cleanable.
+ */
+ private final CleanerImpl cleanerImpl;
+
+ /**
+ * Constructs new {@code WeakCleanableReference} with
+ * {@code non-null referent} and {@code non-null cleaner}.
+ * The {@code cleaner} is not retained by this reference; it is only used
+ * to register the newly constructed {@link Cleaner.Cleanable Cleanable}.
+ *
+ * @param referent the referent to track
+ * @param cleaner the {@code Cleaner} to register new reference with
+ */
+ public WeakCleanable(T referent, Cleaner cleaner) {
+ super(Objects.requireNonNull(referent), getCleanerImpl(cleaner).queue);
+ cleanerImpl = getCleanerImpl(cleaner);
+ insert();
+
+ // TODO: Replace getClass() with ReachabilityFence when it is available
+ cleaner.getClass();
+ referent.getClass();
+ }
+
+ /**
+ * Construct a new root of the list; not inserted.
+ */
+ WeakCleanable(CleanerImpl cleanerImpl) {
+ super(null, null);
+ this.cleanerImpl = cleanerImpl;
+ }
+
+ /**
+ * Insert this WeakCleanableReference after the list head.
+ */
+ private void insert() {
+ final WeakCleanable<?> list = cleanerImpl.weakCleanableList;
+ synchronized (list) {
+ prev = list;
+ next = list.next;
+ next.prev = this;
+ list.next = this;
+ }
+ }
+
+ /**
+ * Remove this WeakCleanableReference from the list.
+ *
+ * @return true if Cleanable was removed or false if not because
+ * it had already been removed before
+ */
+ private boolean remove() {
+ WeakCleanable<?> list = cleanerImpl.weakCleanableList;
+ synchronized (list) {
+ if (next != this) {
+ next.prev = prev;
+ prev.next = next;
+ prev = this;
+ next = this;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the list's next reference refers to itself.
+ *
+ * @return true if the list is empty
+ */
+ boolean isListEmpty() {
+ WeakCleanable<?> list = cleanerImpl.weakCleanableList;
+ synchronized (list) {
+ return list == list.next;
+ }
+ }
+
+ /**
+ * Unregister this WeakCleanable reference and invoke {@link #performCleanup()},
+ * ensuring at-most-once semantics.
+ */
+ @Override
+ public final void clean() {
+ if (remove()) {
+ super.clear();
+ performCleanup();
+ }
+ }
+
+ /**
+ * Unregister this WeakCleanable and clear the reference.
+ * Due to inherent concurrency, {@link #performCleanup()} may still be invoked.
+ */
+ @Override
+ public void clear() {
+ if (remove()) {
+ super.clear();
+ }
+ }
+
+ /**
+ * The {@code performCleanup} abstract method is overridden
+ * to implement the cleaning logic.
+ * The {@code performCleanup} method should not be called except
+ * by the {@link #clean} method which ensures at most once semantics.
+ */
+ protected abstract void performCleanup();
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link java.lang.ref.Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean isEnqueued() {
+ throw new UnsupportedOperationException("isEnqueued");
+ }
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link java.lang.ref.Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean enqueue() {
+ throw new UnsupportedOperationException("enqueue");
+ }
+ }
+
+ /**
+ * SoftCleanable subclasses efficiently encapsulate cleanup state and
+ * the cleaning action.
+ * Subclasses implement the abstract {@link #performCleanup()} method
+ * to provide the cleaning action.
+ * When constructed, the object reference and the {@link Cleanable Cleanable}
+ * are registered with the {@link Cleaner}.
+ * The Cleaner invokes {@link Cleaner.Cleanable#clean() clean} after the
+ * referent becomes softly reachable.
+ */
+ public static abstract class SoftCleanable<T> extends SoftReference<T>
+ implements Cleaner.Cleanable {
+
+ /**
+ * Links to previous and next in a doubly-linked list.
+ */
+ SoftCleanable<?> prev = this, next = this;
+
+ /**
+ * The CleanerImpl for this Cleanable.
+ */
+ private final CleanerImpl cleanerImpl;
+
+ /**
+ * Constructs new {@code SoftCleanableReference} with
+ * {@code non-null referent} and {@code non-null cleaner}.
+ * The {@code cleaner} is not retained by this reference; it is only used
+ * to register the newly constructed {@link Cleaner.Cleanable Cleanable}.
+ *
+ * @param referent the referent to track
+ * @param cleaner the {@code Cleaner} to register with
+ */
+ public SoftCleanable(T referent, Cleaner cleaner) {
+ super(Objects.requireNonNull(referent), getCleanerImpl(cleaner).queue);
+ cleanerImpl = getCleanerImpl(cleaner);
+ insert();
+
+ // TODO: Replace getClass() with ReachabilityFence when it is available
+ cleaner.getClass();
+ referent.getClass();
+ }
+
+ /**
+ * Construct a new root of the list; not inserted.
+ */
+ SoftCleanable(CleanerImpl cleanerImpl) {
+ super(null, null);
+ this.cleanerImpl = cleanerImpl;
+ }
+
+ /**
+ * Insert this SoftCleanableReference after the list head.
+ */
+ private void insert() {
+ final SoftCleanable<?> list = cleanerImpl.softCleanableList;
+ synchronized (list) {
+ prev = list;
+ next = list.next;
+ next.prev = this;
+ list.next = this;
+ }
+ }
+
+ /**
+ * Remove this SoftCleanableReference from the list.
+ *
+ * @return true if Cleanable was removed or false if not because
+ * it had already been removed before
+ */
+ private boolean remove() {
+ SoftCleanable<?> list = cleanerImpl.softCleanableList;
+ synchronized (list) {
+ if (next != this) {
+ next.prev = prev;
+ prev.next = next;
+ prev = this;
+ next = this;
+ return true;
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns true if the list's next reference refers to itself.
+ *
+ * @return true if the list is empty
+ */
+ boolean isListEmpty() {
+ SoftCleanable<?> list = cleanerImpl.softCleanableList;
+ synchronized (list) {
+ return list == list.next;
+ }
+ }
+
+ /**
+ * Unregister this SoftCleanable reference and invoke {@link #performCleanup()},
+ * ensuring at-most-once semantics.
+ */
+ @Override
+ public final void clean() {
+ if (remove()) {
+ super.clear();
+ performCleanup();
+ }
+ }
+
+ /**
+ * Unregister this SoftCleanable and clear the reference.
+ * Due to inherent concurrency, {@link #performCleanup()} may still be invoked.
+ */
+ @Override
+ public void clear() {
+ if (remove()) {
+ super.clear();
+ }
+ }
+
+ /**
+ * The {@code performCleanup} abstract method is overridden
+ * to implement the cleaning logic.
+ * The {@code performCleanup} method should not be called except
+ * by the {@link #clean} method which ensures at most once semantics.
+ */
+ protected abstract void performCleanup();
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean isEnqueued() {
+ throw new UnsupportedOperationException("isEnqueued");
+ }
+
+ /**
+ * This method always throws {@link UnsupportedOperationException}.
+ * Enqueuing details of {@link Cleaner.Cleanable}
+ * are a private implementation detail.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public final boolean enqueue() {
+ throw new UnsupportedOperationException("enqueue");
+ }
+ }
+
+ /**
+ * Perform cleaning on an unreachable PhantomReference.
+ */
+ public static final class PhantomCleanableRef extends PhantomCleanable<Object> {
+ private final Runnable action;
+
+ /**
+ * Constructor for a phantom cleanable reference.
+ * @param obj the object to monitor
+ * @param cleaner the cleaner
+ * @param action the action Runnable
+ */
+ public PhantomCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+ super(obj, cleaner);
+ this.action = action;
+ }
+
+ /**
+ * Constructor used only for root of phantom cleanable list.
+ * @param cleanerImpl the cleanerImpl
+ */
+ PhantomCleanableRef(CleanerImpl cleanerImpl) {
+ super(cleanerImpl);
+ this.action = null;
+ }
+
+ @Override
+ protected void performCleanup() {
+ action.run();
+ }
+
+ /**
+ * Prevent access to referent even when it is still alive.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Object get() {
+ throw new UnsupportedOperationException("get");
+ }
+
+ /**
+ * Direct clearing of the referent is not supported.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("clear");
+ }
+ }
+
+ /**
+ * Perform cleaning on an unreachable WeakReference.
+ */
+ public static final class WeakCleanableRef extends WeakCleanable<Object> {
+ private final Runnable action;
+
+ /**
+ * Constructor for a weak cleanable reference.
+ * @param obj the object to monitor
+ * @param cleaner the cleaner
+ * @param action the action Runnable
+ */
+ WeakCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+ super(obj, cleaner);
+ this.action = action;
+ }
+
+ /**
+ * Constructor used only for root of weak cleanable list.
+ * @param cleanerImpl the cleanerImpl
+ */
+ WeakCleanableRef(CleanerImpl cleanerImpl) {
+ super(cleanerImpl);
+ this.action = null;
+ }
+
+ @Override
+ protected void performCleanup() {
+ action.run();
+ }
+
+ /**
+ * Prevent access to referent even when it is still alive.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Object get() {
+ throw new UnsupportedOperationException("get");
+ }
+
+ /**
+ * Direct clearing of the referent is not supported.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("clear");
+ }
+ }
+
+ /**
+ * Perform cleaning on an unreachable SoftReference.
+ */
+ public static final class SoftCleanableRef extends SoftCleanable<Object> {
+ private final Runnable action;
+
+ /**
+ * Constructor for a soft cleanable reference.
+ * @param obj the object to monitor
+ * @param cleaner the cleaner
+ * @param action the action Runnable
+ */
+ SoftCleanableRef(Object obj, Cleaner cleaner, Runnable action) {
+ super(obj, cleaner);
+ this.action = action;
+ }
+
+ /**
+ * Constructor used only for root of soft cleanable list.
+ * @param cleanerImpl the cleanerImpl
+ */
+ SoftCleanableRef(CleanerImpl cleanerImpl) {
+ super(cleanerImpl);
+ this.action = null;
+ }
+
+ @Override
+ protected void performCleanup() {
+ action.run();
+ }
+
+ /**
+ * Prevent access to referent even when it is still alive.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public Object get() {
+ throw new UnsupportedOperationException("get");
+ }
+
+ /**
+ * Direct clearing of the referent is not supported.
+ *
+ * @throws UnsupportedOperationException always
+ */
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException("clear");
+ }
+
+ }
+
+ /**
+ * A ThreadFactory for InnocuousThreads.
+ * The factory is a singleton.
+ */
+ static final class InnocuousThreadFactory implements ThreadFactory {
+ final static ThreadFactory factory = new InnocuousThreadFactory();
+
+ static ThreadFactory factory() {
+ return factory;
+ }
+
+ public Thread newThread(Runnable r) {
+ return AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
+ Thread t = new InnocuousThread(r);
+ t.setPriority(Thread.MAX_PRIORITY - 2);
+ t.setName("Cleaner-" + t.getId());
+ return t;
+ });
+ }
+ }
+
+}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilZipFileAccess.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,5 +29,6 @@
public interface JavaUtilZipFileAccess {
public boolean startsWithLocHeader(ZipFile zip);
+ public String[] getMetaInfEntryNames(ZipFile zip);
}
--- a/jdk/src/java.base/share/classes/sun/misc/BASE64Decoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 1995, 2011, 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.misc;
-
-import java.io.OutputStream;
-import java.io.PushbackInputStream;
-import java.io.PrintStream;
-
-/**
- * This class implements a BASE64 Character decoder as specified in RFC1521.
- *
- * This RFC is part of the MIME specification which is published by the
- * Internet Engineering Task Force (IETF). Unlike some other encoding
- * schemes there is nothing in this encoding that tells the decoder
- * where a buffer starts or stops, so to use it you will need to isolate
- * your encoded data into a single chunk and then feed them this decoder.
- * The simplest way to do that is to read all of the encoded data into a
- * string and then use:
- * <pre>
- * byte mydata[];
- * BASE64Decoder base64 = new BASE64Decoder();
- *
- * mydata = base64.decodeBuffer(bufferString);
- * </pre>
- * This will decode the String in <i>bufferString</i> and give you an array
- * of bytes in the array <i>myData</i>.
- *
- * On errors, this class throws a CEFormatException with the following detail
- * strings:
- * <pre>
- * "BASE64Decoder: Not enough bytes for an atom."
- * </pre>
- *
- * @author Chuck McManis
- * @see CharacterEncoder
- * @see BASE64Decoder
- */
-
-public class BASE64Decoder extends CharacterDecoder {
-
- /** This class has 4 bytes per atom */
- protected int bytesPerAtom() {
- return (4);
- }
-
- /** Any multiple of 4 will do, 72 might be common */
- protected int bytesPerLine() {
- return (72);
- }
-
- /**
- * This character array provides the character to value map
- * based on RFC1521.
- */
- private static final char pem_array[] = {
- // 0 1 2 3 4 5 6 7
- 'A','B','C','D','E','F','G','H', // 0
- 'I','J','K','L','M','N','O','P', // 1
- 'Q','R','S','T','U','V','W','X', // 2
- 'Y','Z','a','b','c','d','e','f', // 3
- 'g','h','i','j','k','l','m','n', // 4
- 'o','p','q','r','s','t','u','v', // 5
- 'w','x','y','z','0','1','2','3', // 6
- '4','5','6','7','8','9','+','/' // 7
- };
-
- private static final byte pem_convert_array[] = new byte[256];
-
- static {
- for (int i = 0; i < 255; i++) {
- pem_convert_array[i] = -1;
- }
- for (int i = 0; i < pem_array.length; i++) {
- pem_convert_array[pem_array[i]] = (byte) i;
- }
- }
-
- byte decode_buffer[] = new byte[4];
-
- /**
- * Decode one BASE64 atom into 1, 2, or 3 bytes of data.
- */
- @SuppressWarnings("fallthrough")
- protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem)
- throws java.io.IOException
- {
- int i;
- byte a = -1, b = -1, c = -1, d = -1;
-
- if (rem < 2) {
- throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
- }
- do {
- i = inStream.read();
- if (i == -1) {
- throw new CEStreamExhausted();
- }
- } while (i == '\n' || i == '\r');
- decode_buffer[0] = (byte) i;
-
- i = readFully(inStream, decode_buffer, 1, rem-1);
- if (i == -1) {
- throw new CEStreamExhausted();
- }
-
- if (rem > 3 && decode_buffer[3] == '=') {
- rem = 3;
- }
- if (rem > 2 && decode_buffer[2] == '=') {
- rem = 2;
- }
- switch (rem) {
- case 4:
- d = pem_convert_array[decode_buffer[3] & 0xff];
- // NOBREAK
- case 3:
- c = pem_convert_array[decode_buffer[2] & 0xff];
- // NOBREAK
- case 2:
- b = pem_convert_array[decode_buffer[1] & 0xff];
- a = pem_convert_array[decode_buffer[0] & 0xff];
- break;
- }
-
- switch (rem) {
- case 2:
- outStream.write( (byte)(((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
- break;
- case 3:
- outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
- outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
- break;
- case 4:
- outStream.write( (byte) (((a << 2) & 0xfc) | ((b >>> 4) & 3)) );
- outStream.write( (byte) (((b << 4) & 0xf0) | ((c >>> 2) & 0xf)) );
- outStream.write( (byte) (((c << 6) & 0xc0) | (d & 0x3f)) );
- break;
- }
- return;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/BASE64Encoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, 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.misc;
-
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a BASE64 Character encoder as specified in RFC1521.
- * This RFC is part of the MIME specification as published by the Internet
- * Engineering Task Force (IETF). Unlike some other encoding schemes there
- * is nothing in this encoding that indicates
- * where a buffer starts or ends.
- *
- * This means that the encoded text will simply start with the first line
- * of encoded text and end with the last line of encoded text.
- *
- * @author Chuck McManis
- * @see CharacterEncoder
- * @see BASE64Decoder
- */
-
-public class BASE64Encoder extends CharacterEncoder {
-
- /** this class encodes three bytes per atom. */
- protected int bytesPerAtom() {
- return (3);
- }
-
- /**
- * this class encodes 57 bytes per line. This results in a maximum
- * of 57/3 * 4 or 76 characters per output line. Not counting the
- * line termination.
- */
- protected int bytesPerLine() {
- return (57);
- }
-
- /** This array maps the characters to their 6 bit values */
- private static final char pem_array[] = {
- // 0 1 2 3 4 5 6 7
- 'A','B','C','D','E','F','G','H', // 0
- 'I','J','K','L','M','N','O','P', // 1
- 'Q','R','S','T','U','V','W','X', // 2
- 'Y','Z','a','b','c','d','e','f', // 3
- 'g','h','i','j','k','l','m','n', // 4
- 'o','p','q','r','s','t','u','v', // 5
- 'w','x','y','z','0','1','2','3', // 6
- '4','5','6','7','8','9','+','/' // 7
- };
-
- /**
- * encodeAtom - Take three bytes of input and encode it as 4
- * printable characters. Note that if the length in len is less
- * than three is encodes either one or two '=' signs to indicate
- * padding characters.
- */
- protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len)
- throws IOException {
- byte a, b, c;
-
- if (len == 1) {
- a = data[offset];
- b = 0;
- c = 0;
- outStream.write(pem_array[(a >>> 2) & 0x3F]);
- outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
- outStream.write('=');
- outStream.write('=');
- } else if (len == 2) {
- a = data[offset];
- b = data[offset+1];
- c = 0;
- outStream.write(pem_array[(a >>> 2) & 0x3F]);
- outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
- outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
- outStream.write('=');
- } else {
- a = data[offset];
- b = data[offset+1];
- c = data[offset+2];
- outStream.write(pem_array[(a >>> 2) & 0x3F]);
- outStream.write(pem_array[((a << 4) & 0x30) + ((b >>> 4) & 0xf)]);
- outStream.write(pem_array[((b << 2) & 0x3c) + ((c >>> 6) & 0x3)]);
- outStream.write(pem_array[c & 0x3F]);
- }
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/CharacterDecoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.misc;
-
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.PushbackInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class defines the decoding half of character encoders.
- * A character decoder is an algorithim for transforming 8 bit
- * binary data that has been encoded into text by a character
- * encoder, back into original binary form.
- *
- * The character encoders, in general, have been structured
- * around a central theme that binary data can be encoded into
- * text that has the form:
- *
- * <pre>
- * [Buffer Prefix]
- * [Line Prefix][encoded data atoms][Line Suffix]
- * [Buffer Suffix]
- * </pre>
- *
- * Of course in the simplest encoding schemes, the buffer has no
- * distinct prefix of suffix, however all have some fixed relationship
- * between the text in an 'atom' and the binary data itself.
- *
- * In the CharacterEncoder and CharacterDecoder classes, one complete
- * chunk of data is referred to as a <i>buffer</i>. Encoded buffers
- * are all text, and decoded buffers (sometimes just referred to as
- * buffers) are binary octets.
- *
- * To create a custom decoder, you must, at a minimum, overide three
- * abstract methods in this class.
- * <DL>
- * <DD>bytesPerAtom which tells the decoder how many bytes to
- * expect from decodeAtom
- * <DD>decodeAtom which decodes the bytes sent to it as text.
- * <DD>bytesPerLine which tells the encoder the maximum number of
- * bytes per line.
- * </DL>
- *
- * In general, the character decoders return error in the form of a
- * CEFormatException. The syntax of the detail string is
- * <pre>
- * DecoderClassName: Error message.
- * </pre>
- *
- * Several useful decoders have already been written and are
- * referenced in the See Also list below.
- *
- * @author Chuck McManis
- * @see CEFormatException
- * @see CharacterEncoder
- * @see UCDecoder
- * @see UUDecoder
- * @see BASE64Decoder
- */
-
-public abstract class CharacterDecoder {
-
- /** Return the number of bytes per atom of decoding */
- protected abstract int bytesPerAtom();
-
- /** Return the maximum number of bytes that can be encoded per line */
- protected abstract int bytesPerLine();
-
- /** decode the beginning of the buffer, by default this is a NOP. */
- protected void decodeBufferPrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
- /** decode the buffer suffix, again by default it is a NOP. */
- protected void decodeBufferSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
- /**
- * This method should return, if it knows, the number of bytes
- * that will be decoded. Many formats such as uuencoding provide
- * this information. By default we return the maximum bytes that
- * could have been encoded on the line.
- */
- protected int decodeLinePrefix(PushbackInputStream aStream, OutputStream bStream) throws IOException {
- return (bytesPerLine());
- }
-
- /**
- * This method post processes the line, if there are error detection
- * or correction codes in a line, they are generally processed by
- * this method. The simplest version of this method looks for the
- * (newline) character.
- */
- protected void decodeLineSuffix(PushbackInputStream aStream, OutputStream bStream) throws IOException { }
-
- /**
- * This method does an actual decode. It takes the decoded bytes and
- * writes them to the OutputStream. The integer <i>l</i> tells the
- * method how many bytes are required. This is always {@literal <=} bytesPerAtom().
- */
- protected void decodeAtom(PushbackInputStream aStream, OutputStream bStream, int l) throws IOException {
- throw new CEStreamExhausted();
- }
-
- /**
- * This method works around the bizarre semantics of BufferedInputStream's
- * read method.
- */
- protected int readFully(InputStream in, byte buffer[], int offset, int len)
- throws java.io.IOException {
- for (int i = 0; i < len; i++) {
- int q = in.read();
- if (q == -1)
- return ((i == 0) ? -1 : i);
- buffer[i+offset] = (byte)q;
- }
- return len;
- }
-
- /**
- * Decode the text from the InputStream and write the decoded
- * octets to the OutputStream. This method runs until the stream
- * is exhausted.
- * @exception CEFormatException An error has occurred while decoding
- * @exception CEStreamExhausted The input stream is unexpectedly out of data
- */
- public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException {
- int i;
- int totalBytes = 0;
-
- PushbackInputStream ps = new PushbackInputStream (aStream);
- decodeBufferPrefix(ps, bStream);
- while (true) {
- int length;
-
- try {
- length = decodeLinePrefix(ps, bStream);
- for (i = 0; (i+bytesPerAtom()) < length; i += bytesPerAtom()) {
- decodeAtom(ps, bStream, bytesPerAtom());
- totalBytes += bytesPerAtom();
- }
- if ((i + bytesPerAtom()) == length) {
- decodeAtom(ps, bStream, bytesPerAtom());
- totalBytes += bytesPerAtom();
- } else {
- decodeAtom(ps, bStream, length - i);
- totalBytes += (length - i);
- }
- decodeLineSuffix(ps, bStream);
- } catch (CEStreamExhausted e) {
- break;
- }
- }
- decodeBufferSuffix(ps, bStream);
- }
-
- /**
- * Alternate decode interface that takes a String containing the encoded
- * buffer and returns a byte array containing the data.
- * @exception CEFormatException An error has occurred while decoding
- */
- public byte[] decodeBuffer(String inputString) throws IOException {
- byte inputBuffer[] = inputString.getBytes("ISO-8859-1");
- ByteArrayInputStream inStream = new ByteArrayInputStream(inputBuffer);
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- decodeBuffer(inStream, outStream);
- return outStream.toByteArray();
- }
-
- /**
- * Decode the contents of the inputstream into a buffer.
- */
- public byte[] decodeBuffer(InputStream in) throws IOException {
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- decodeBuffer(in, outStream);
- return outStream.toByteArray();
- }
-
- /**
- * Decode the contents of the String into a ByteBuffer.
- */
- public ByteBuffer decodeBufferToByteBuffer(String inputString)
- throws IOException {
- return ByteBuffer.wrap(decodeBuffer(inputString));
- }
-
- /**
- * Decode the contents of the inputStream into a ByteBuffer.
- */
- public ByteBuffer decodeBufferToByteBuffer(InputStream in)
- throws IOException {
- return ByteBuffer.wrap(decodeBuffer(in));
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/CharacterEncoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-/*
- * Copyright (c) 1995, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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.misc;
-
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-
-/**
- * This class defines the encoding half of character encoders.
- * A character encoder is an algorithim for transforming 8 bit binary
- * data into text (generally 7 bit ASCII or 8 bit ISO-Latin-1 text)
- * for transmition over text channels such as e-mail and network news.
- *
- * The character encoders have been structured around a central theme
- * that, in general, the encoded text has the form:
- *
- * <pre>
- * [Buffer Prefix]
- * [Line Prefix][encoded data atoms][Line Suffix]
- * [Buffer Suffix]
- * </pre>
- *
- * In the CharacterEncoder and CharacterDecoder classes, one complete
- * chunk of data is referred to as a <i>buffer</i>. Encoded buffers
- * are all text, and decoded buffers (sometimes just referred to as
- * buffers) are binary octets.
- *
- * To create a custom encoder, you must, at a minimum, overide three
- * abstract methods in this class.
- * <DL>
- * <DD>bytesPerAtom which tells the encoder how many bytes to
- * send to encodeAtom
- * <DD>encodeAtom which encodes the bytes sent to it as text.
- * <DD>bytesPerLine which tells the encoder the maximum number of
- * bytes per line.
- * </DL>
- *
- * Several useful encoders have already been written and are
- * referenced in the See Also list below.
- *
- * @author Chuck McManis
- * @see CharacterDecoder
- * @see UCEncoder
- * @see UUEncoder
- * @see BASE64Encoder
- */
-public abstract class CharacterEncoder {
-
- /** Stream that understands "printing" */
- protected PrintStream pStream;
-
- /** Return the number of bytes per atom of encoding */
- protected abstract int bytesPerAtom();
-
- /** Return the number of bytes that can be encoded per line */
- protected abstract int bytesPerLine();
-
- /**
- * Encode the prefix for the entire buffer. By default is simply
- * opens the PrintStream for use by the other functions.
- */
- protected void encodeBufferPrefix(OutputStream aStream) throws IOException {
- pStream = new PrintStream(aStream);
- }
-
- /**
- * Encode the suffix for the entire buffer.
- */
- protected void encodeBufferSuffix(OutputStream aStream) throws IOException {
- }
-
- /**
- * Encode the prefix that starts every output line.
- */
- protected void encodeLinePrefix(OutputStream aStream, int aLength)
- throws IOException {
- }
-
- /**
- * Encode the suffix that ends every output line. By default
- * this method just prints a newline into the output stream.
- */
- protected void encodeLineSuffix(OutputStream aStream) throws IOException {
- pStream.println();
- }
-
- /** Encode one "atom" of information into characters. */
- protected abstract void encodeAtom(OutputStream aStream, byte someBytes[],
- int anOffset, int aLength) throws IOException;
-
- /**
- * This method works around the bizarre semantics of BufferedInputStream's
- * read method.
- */
- protected int readFully(InputStream in, byte buffer[])
- throws java.io.IOException {
- for (int i = 0; i < buffer.length; i++) {
- int q = in.read();
- if (q == -1)
- return i;
- buffer[i] = (byte)q;
- }
- return buffer.length;
- }
-
- /**
- * Encode bytes from the input stream, and write them as text characters
- * to the output stream. This method will run until it exhausts the
- * input stream, but does not print the line suffix for a final
- * line that is shorter than bytesPerLine().
- */
- public void encode(InputStream inStream, OutputStream outStream)
- throws IOException {
- int j;
- int numBytes;
- byte tmpbuffer[] = new byte[bytesPerLine()];
-
- encodeBufferPrefix(outStream);
-
- while (true) {
- numBytes = readFully(inStream, tmpbuffer);
- if (numBytes == 0) {
- break;
- }
- encodeLinePrefix(outStream, numBytes);
- for (j = 0; j < numBytes; j += bytesPerAtom()) {
-
- if ((j + bytesPerAtom()) <= numBytes) {
- encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
- } else {
- encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
- }
- }
- if (numBytes < bytesPerLine()) {
- break;
- } else {
- encodeLineSuffix(outStream);
- }
- }
- encodeBufferSuffix(outStream);
- }
-
- /**
- * Encode the buffer in <i>aBuffer</i> and write the encoded
- * result to the OutputStream <i>aStream</i>.
- */
- public void encode(byte aBuffer[], OutputStream aStream)
- throws IOException {
- ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
- encode(inStream, aStream);
- }
-
- /**
- * A 'streamless' version of encode that simply takes a buffer of
- * bytes and returns a string containing the encoded buffer.
- */
- public String encode(byte aBuffer[]) {
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
- String retVal = null;
- try {
- encode(inStream, outStream);
- // explicit ascii->unicode conversion
- retVal = outStream.toString("ISO-8859-1");
- } catch (Exception IOException) {
- // This should never happen.
- throw new Error("CharacterEncoder.encode internal error");
- }
- return (retVal);
- }
-
- /**
- * Return a byte array from the remaining bytes in this ByteBuffer.
- * <P>
- * The ByteBuffer's position will be advanced to ByteBuffer's limit.
- * <P>
- * To avoid an extra copy, the implementation will attempt to return the
- * byte array backing the ByteBuffer. If this is not possible, a
- * new byte array will be created.
- */
- private byte [] getBytes(ByteBuffer bb) {
- /*
- * This should never return a BufferOverflowException, as we're
- * careful to allocate just the right amount.
- */
- byte [] buf = null;
-
- /*
- * If it has a usable backing byte buffer, use it. Use only
- * if the array exactly represents the current ByteBuffer.
- */
- if (bb.hasArray()) {
- byte [] tmp = bb.array();
- if ((tmp.length == bb.capacity()) &&
- (tmp.length == bb.remaining())) {
- buf = tmp;
- bb.position(bb.limit());
- }
- }
-
- if (buf == null) {
- /*
- * This class doesn't have a concept of encode(buf, len, off),
- * so if we have a partial buffer, we must reallocate
- * space.
- */
- buf = new byte[bb.remaining()];
-
- /*
- * position() automatically updated
- */
- bb.get(buf);
- }
-
- return buf;
- }
-
- /**
- * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
- * result to the OutputStream <i>aStream</i>.
- * <P>
- * The ByteBuffer's position will be advanced to ByteBuffer's limit.
- */
- public void encode(ByteBuffer aBuffer, OutputStream aStream)
- throws IOException {
- byte [] buf = getBytes(aBuffer);
- encode(buf, aStream);
- }
-
- /**
- * A 'streamless' version of encode that simply takes a ByteBuffer
- * and returns a string containing the encoded buffer.
- * <P>
- * The ByteBuffer's position will be advanced to ByteBuffer's limit.
- */
- public String encode(ByteBuffer aBuffer) {
- byte [] buf = getBytes(aBuffer);
- return encode(buf);
- }
-
- /**
- * Encode bytes from the input stream, and write them as text characters
- * to the output stream. This method will run until it exhausts the
- * input stream. It differs from encode in that it will add the
- * line at the end of a final line that is shorter than bytesPerLine().
- */
- public void encodeBuffer(InputStream inStream, OutputStream outStream)
- throws IOException {
- int j;
- int numBytes;
- byte tmpbuffer[] = new byte[bytesPerLine()];
-
- encodeBufferPrefix(outStream);
-
- while (true) {
- numBytes = readFully(inStream, tmpbuffer);
- if (numBytes == 0) {
- break;
- }
- encodeLinePrefix(outStream, numBytes);
- for (j = 0; j < numBytes; j += bytesPerAtom()) {
- if ((j + bytesPerAtom()) <= numBytes) {
- encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
- } else {
- encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
- }
- }
- encodeLineSuffix(outStream);
- if (numBytes < bytesPerLine()) {
- break;
- }
- }
- encodeBufferSuffix(outStream);
- }
-
- /**
- * Encode the buffer in <i>aBuffer</i> and write the encoded
- * result to the OutputStream <i>aStream</i>.
- */
- public void encodeBuffer(byte aBuffer[], OutputStream aStream)
- throws IOException {
- ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
- encodeBuffer(inStream, aStream);
- }
-
- /**
- * A 'streamless' version of encode that simply takes a buffer of
- * bytes and returns a string containing the encoded buffer.
- */
- public String encodeBuffer(byte aBuffer[]) {
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
- try {
- encodeBuffer(inStream, outStream);
- } catch (Exception IOException) {
- // This should never happen.
- throw new Error("CharacterEncoder.encodeBuffer internal error");
- }
- return (outStream.toString());
- }
-
- /**
- * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
- * result to the OutputStream <i>aStream</i>.
- * <P>
- * The ByteBuffer's position will be advanced to ByteBuffer's limit.
- */
- public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
- throws IOException {
- byte [] buf = getBytes(aBuffer);
- encodeBuffer(buf, aStream);
- }
-
- /**
- * A 'streamless' version of encode that simply takes a ByteBuffer
- * and returns a string containing the encoded buffer.
- * <P>
- * The ByteBuffer's position will be advanced to ByteBuffer's limit.
- */
- public String encodeBuffer(ByteBuffer aBuffer) {
- byte [] buf = getBytes(aBuffer);
- return encodeBuffer(buf);
- }
-
-}
--- a/jdk/src/java.base/share/classes/sun/misc/CompoundEnumeration.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, 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.misc;
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-/*
- * A useful utility class that will enumerate over an array of
- * enumerations.
- */
-public class CompoundEnumeration<E> implements Enumeration<E> {
- private Enumeration<E>[] enums;
- private int index = 0;
-
- public CompoundEnumeration(Enumeration<E>[] enums) {
- this.enums = enums;
- }
-
- private boolean next() {
- while (index < enums.length) {
- if (enums[index] != null && enums[index].hasMoreElements()) {
- return true;
- }
- index++;
- }
- return false;
- }
-
- public boolean hasMoreElements() {
- return next();
- }
-
- public E nextElement() {
- if (!next()) {
- throw new NoSuchElementException();
- }
- return enums[index].nextElement();
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/DoubleConsts.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2003, 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. 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.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>double</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-public class DoubleConsts {
- /**
- * Don't let anyone instantiate this class.
- */
- private DoubleConsts() {}
-
- public static final double POSITIVE_INFINITY = java.lang.Double.POSITIVE_INFINITY;
- public static final double NEGATIVE_INFINITY = java.lang.Double.NEGATIVE_INFINITY;
- public static final double NaN = java.lang.Double.NaN;
- public static final double MAX_VALUE = java.lang.Double.MAX_VALUE;
- public static final double MIN_VALUE = java.lang.Double.MIN_VALUE;
-
- /**
- * A constant holding the smallest positive normal value of type
- * <code>double</code>, 2<sup>-1022</sup>. It is equal to the
- * value returned by
- * <code>Double.longBitsToDouble(0x0010000000000000L)</code>.
- *
- * @since 1.5
- */
- public static final double MIN_NORMAL = 2.2250738585072014E-308;
-
-
- /**
- * The number of logical bits in the significand of a
- * <code>double</code> number, including the implicit bit.
- */
- public static final int SIGNIFICAND_WIDTH = 53;
-
- /**
- * Maximum exponent a finite <code>double</code> number may have.
- * It is equal to the value returned by
- * <code>Math.ilogb(Double.MAX_VALUE)</code>.
- */
- public static final int MAX_EXPONENT = 1023;
-
- /**
- * Minimum exponent a normalized <code>double</code> number may
- * have. It is equal to the value returned by
- * <code>Math.ilogb(Double.MIN_NORMAL)</code>.
- */
- public static final int MIN_EXPONENT = -1022;
-
- /**
- * The exponent the smallest positive <code>double</code>
- * subnormal value would have if it could be normalized..
- */
- public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
- (SIGNIFICAND_WIDTH - 1);
-
- /**
- * Bias used in representing a <code>double</code> exponent.
- */
- public static final int EXP_BIAS = 1023;
-
- /**
- * Bit mask to isolate the sign bit of a <code>double</code>.
- */
- public static final long SIGN_BIT_MASK = 0x8000000000000000L;
-
- /**
- * Bit mask to isolate the exponent field of a
- * <code>double</code>.
- */
- public static final long EXP_BIT_MASK = 0x7FF0000000000000L;
-
- /**
- * Bit mask to isolate the significand field of a
- * <code>double</code>.
- */
- public static final long SIGNIF_BIT_MASK = 0x000FFFFFFFFFFFFFL;
-
- static {
- // verify bit masks cover all bit positions and that the bit
- // masks are non-overlapping
- assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0L) &&
- (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0L) &&
- ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0L) &&
- ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0L)));
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FDBigInteger.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1508 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.misc;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-//@ model import org.jmlspecs.models.JMLMath;
-
-/**
- * A simple big integer package specifically for floating point base conversion.
- */
-public /*@ spec_bigint_math @*/ class FDBigInteger {
-
- //
- // This class contains many comments that start with "/*@" mark.
- // They are behavourial specification in
- // the Java Modelling Language (JML):
- // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
- //
-
- /*@
- @ public pure model static \bigint UNSIGNED(int v) {
- @ return v >= 0 ? v : v + (((\bigint)1) << 32);
- @ }
- @
- @ public pure model static \bigint UNSIGNED(long v) {
- @ return v >= 0 ? v : v + (((\bigint)1) << 64);
- @ }
- @
- @ public pure model static \bigint AP(int[] data, int len) {
- @ return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
- @ }
- @
- @ public pure model static \bigint pow52(int p5, int p2) {
- @ ghost \bigint v = 1;
- @ for (int i = 0; i < p5; i++) v *= 5;
- @ return v << p2;
- @ }
- @
- @ public pure model static \bigint pow10(int p10) {
- @ return pow52(p10, p10);
- @ }
- @*/
-
- static final int[] SMALL_5_POW = {
- 1,
- 5,
- 5 * 5,
- 5 * 5 * 5,
- 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
- };
-
- static final long[] LONG_5_POW = {
- 1L,
- 5L,
- 5L * 5,
- 5L * 5 * 5,
- 5L * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- 5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
- };
-
- // Maximum size of cache of powers of 5 as FDBigIntegers.
- private static final int MAX_FIVE_POW = 340;
-
- // Cache of big powers of 5 as FDBigIntegers.
- private static final FDBigInteger POW_5_CACHE[];
-
- // Initialize FDBigInteger cache of powers of 5.
- static {
- POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
- int i = 0;
- while (i < SMALL_5_POW.length) {
- FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
- pow5.makeImmutable();
- POW_5_CACHE[i] = pow5;
- i++;
- }
- FDBigInteger prev = POW_5_CACHE[i - 1];
- while (i < MAX_FIVE_POW) {
- POW_5_CACHE[i] = prev = prev.mult(5);
- prev.makeImmutable();
- i++;
- }
- }
-
- // Zero as an FDBigInteger.
- public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
-
- // Ensure ZERO is immutable.
- static {
- ZERO.makeImmutable();
- }
-
- // Constant for casting an int to a long via bitwise AND.
- private static final long LONG_MASK = 0xffffffffL;
-
- //@ spec_public non_null;
- private int data[]; // value: data[0] is least significant
- //@ spec_public;
- private int offset; // number of least significant zero padding ints
- //@ spec_public;
- private int nWords; // data[nWords-1]!=0, all values above are zero
- // if nWords==0 -> this FDBigInteger is zero
- //@ spec_public;
- private boolean isImmutable = false;
-
- /*@
- @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
- @ public invariant nWords == 0 ==> offset == 0;
- @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
- @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
- @ public pure model \bigint value() {
- @ return AP(data, nWords) << (offset*32);
- @ }
- @*/
-
- /**
- * Constructs an <code>FDBigInteger</code> from data and padding. The
- * <code>data</code> parameter has the least significant <code>int</code> at
- * the zeroth index. The <code>offset</code> parameter gives the number of
- * zero <code>int</code>s to be inferred below the least significant element
- * of <code>data</code>.
- *
- * @param data An array containing all non-zero <code>int</code>s of the value.
- * @param offset An offset indicating the number of zero <code>int</code>s to pad
- * below the least significant element of <code>data</code>.
- */
- /*@
- @ requires data != null && offset >= 0;
- @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
- @ ensures this.data == \old(data);
- @*/
- private FDBigInteger(int[] data, int offset) {
- this.data = data;
- this.offset = offset;
- this.nWords = data.length;
- trimLeadingZeros();
- }
-
- /**
- * Constructs an <code>FDBigInteger</code> from a starting value and some
- * decimal digits.
- *
- * @param lValue The starting value.
- * @param digits The decimal digits.
- * @param kDigits The initial index into <code>digits</code>.
- * @param nDigits The final index into <code>digits</code>.
- */
- /*@
- @ requires digits != null;
- @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
- @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
- @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
- @*/
- public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
- int n = Math.max((nDigits + 8) / 9, 2); // estimate size needed.
- data = new int[n]; // allocate enough space
- data[0] = (int) lValue; // starting value
- data[1] = (int) (lValue >>> 32);
- offset = 0;
- nWords = 2;
- int i = kDigits;
- int limit = nDigits - 5; // slurp digits 5 at a time.
- int v;
- while (i < limit) {
- int ilim = i + 5;
- v = (int) digits[i++] - (int) '0';
- while (i < ilim) {
- v = 10 * v + (int) digits[i++] - (int) '0';
- }
- multAddMe(100000, v); // ... where 100000 is 10^5.
- }
- int factor = 1;
- v = 0;
- while (i < nDigits) {
- v = 10 * v + (int) digits[i++] - (int) '0';
- factor *= 10;
- }
- if (factor != 1) {
- multAddMe(factor, v);
- }
- trimLeadingZeros();
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
- *
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return <code>5<sup>p5</sup> * 2<sup>p2</sup></code>
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(pow52(p5, p2));
- @*/
- public static FDBigInteger valueOfPow52(int p5, int p2) {
- if (p5 != 0) {
- if (p2 == 0) {
- return big5pow(p5);
- } else if (p5 < SMALL_5_POW.length) {
- int pow5 = SMALL_5_POW[p5];
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{pow5}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- pow5 << bitcount,
- pow5 >>> (32 - bitcount)
- }, wordcount);
- }
- } else {
- return big5pow(p5).leftShift(p2);
- }
- } else {
- return valueOfPow2(p2);
- }
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>.
- *
- * @param value The constant factor.
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return <code>value * 5<sup>p5</sup> * 2<sup>p2</sup></code>
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
- @*/
- public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
- assert p5 >= 0 : p5;
- assert p2 >= 0 : p2;
- int v0 = (int) value;
- int v1 = (int) (value >>> 32);
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- if (p5 != 0) {
- if (p5 < SMALL_5_POW.length) {
- long pow5 = SMALL_5_POW[p5] & LONG_MASK;
- long carry = (v0 & LONG_MASK) * pow5;
- v0 = (int) carry;
- carry >>>= 32;
- carry = (v1 & LONG_MASK) * pow5 + carry;
- v1 = (int) carry;
- int v2 = (int) (carry >>> 32);
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- v0 << bitcount,
- (v1 << bitcount) | (v0 >>> (32 - bitcount)),
- (v2 << bitcount) | (v1 >>> (32 - bitcount)),
- v2 >>> (32 - bitcount)
- }, wordcount);
- }
- } else {
- FDBigInteger pow5 = big5pow(p5);
- int[] r;
- if (v1 == 0) {
- r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
- mult(pow5.data, pow5.nWords, v0, r);
- } else {
- r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
- mult(pow5.data, pow5.nWords, v0, v1, r);
- }
- return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
- }
- } else if (p2 != 0) {
- if (bitcount == 0) {
- return new FDBigInteger(new int[]{v0, v1}, wordcount);
- } else {
- return new FDBigInteger(new int[]{
- v0 << bitcount,
- (v1 << bitcount) | (v0 >>> (32 - bitcount)),
- v1 >>> (32 - bitcount)
- }, wordcount);
- }
- }
- return new FDBigInteger(new int[]{v0, v1}, 0);
- }
-
- /**
- * Returns an <code>FDBigInteger</code> with the numerical value
- * <code>2<sup>p2</sup></code>.
- *
- * @param p2 The exponent of 2.
- * @return <code>2<sup>p2</sup></code>
- */
- /*@
- @ requires p2 >= 0;
- @ assignable \nothing;
- @ ensures \result.value() == pow52(0, p2);
- @*/
- private static FDBigInteger valueOfPow2(int p2) {
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
- }
-
- /**
- * Removes all leading zeros from this <code>FDBigInteger</code> adjusting
- * the offset and number of non-zero leading words accordingly.
- */
- /*@
- @ requires data != null;
- @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
- @ requires nWords == 0 ==> offset == 0;
- @ ensures nWords == 0 ==> offset == 0;
- @ ensures nWords > 0 ==> data[nWords - 1] != 0;
- @*/
- private /*@ helper @*/ void trimLeadingZeros() {
- int i = nWords;
- if (i > 0 && (data[--i] == 0)) {
- //for (; i > 0 && data[i - 1] == 0; i--) ;
- while(i > 0 && data[i - 1] == 0) {
- i--;
- }
- this.nWords = i;
- if (i == 0) { // all words are zero
- this.offset = 0;
- }
- }
- }
-
- /**
- * Retrieves the normalization bias of the <code>FDBigIntger</code>. The
- * normalization bias is a left shift such that after it the highest word
- * of the value will have the 4 highest bits equal to zero:
- * {@code (highestWord & 0xf0000000) == 0}, but the next bit should be 1
- * {@code (highestWord & 0x08000000) != 0}.
- *
- * @return The normalization bias.
- */
- /*@
- @ requires this.value() > 0;
- @*/
- public /*@ pure @*/ int getNormalizationBias() {
- if (nWords == 0) {
- throw new IllegalArgumentException("Zero value cannot be normalized");
- }
- int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
- return (zeros < 4) ? 28 + zeros : zeros - 4;
- }
-
- // TODO: Why is anticount param needed if it is always 32 - bitcount?
- /**
- * Left shifts the contents of one int array into another.
- *
- * @param src The source array.
- * @param idx The initial index of the source array.
- * @param result The destination array.
- * @param bitcount The left shift.
- * @param anticount The left anti-shift, e.g., <code>32-bitcount</code>.
- * @param prev The prior source value.
- */
- /*@
- @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
- @ requires src.length >= idx && result.length > idx;
- @ assignable result[*];
- @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
- @*/
- private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
- for (; idx > 0; idx--) {
- int v = (prev << bitcount);
- prev = src[idx - 1];
- v |= (prev >>> anticount);
- result[idx] = v;
- }
- int v = prev << bitcount;
- result[0] = v;
- }
-
- /**
- * Shifts this <code>FDBigInteger</code> to the left. The shift is performed
- * in-place unless the <code>FDBigInteger</code> is immutable in which case
- * a new instance of <code>FDBigInteger</code> is returned.
- *
- * @param shift The number of bits to shift left.
- * @return The shifted <code>FDBigInteger</code>.
- */
- /*@
- @ requires this.value() == 0 || shift == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && shift > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() << shift);
- @
- @ also
- @
- @ requires this.value() > 0 && shift > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() << shift);
- @*/
- public FDBigInteger leftShift(int shift) {
- if (shift == 0 || nWords == 0) {
- return this;
- }
- int wordcount = shift >> 5;
- int bitcount = shift & 0x1f;
- if (this.isImmutable) {
- if (bitcount == 0) {
- return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
- } else {
- int anticount = 32 - bitcount;
- int idx = nWords - 1;
- int prev = data[idx];
- int hi = prev >>> anticount;
- int[] result;
- if (hi != 0) {
- result = new int[nWords + 1];
- result[nWords] = hi;
- } else {
- result = new int[nWords];
- }
- leftShift(data,idx,result,bitcount,anticount,prev);
- return new FDBigInteger(result, offset + wordcount);
- }
- } else {
- if (bitcount != 0) {
- int anticount = 32 - bitcount;
- if ((data[0] << bitcount) == 0) {
- int idx = 0;
- int prev = data[idx];
- for (; idx < nWords - 1; idx++) {
- int v = (prev >>> anticount);
- prev = data[idx + 1];
- v |= (prev << bitcount);
- data[idx] = v;
- }
- int v = prev >>> anticount;
- data[idx] = v;
- if(v==0) {
- nWords--;
- }
- offset++;
- } else {
- int idx = nWords - 1;
- int prev = data[idx];
- int hi = prev >>> anticount;
- int[] result = data;
- int[] src = data;
- if (hi != 0) {
- if(nWords == data.length) {
- data = result = new int[nWords + 1];
- }
- result[nWords++] = hi;
- }
- leftShift(src,idx,result,bitcount,anticount,prev);
- }
- }
- offset += wordcount;
- return this;
- }
- }
-
- /**
- * Returns the number of <code>int</code>s this <code>FDBigInteger</code> represents.
- *
- * @return Number of <code>int</code>s required to represent this <code>FDBigInteger</code>.
- */
- /*@
- @ requires this.value() == 0;
- @ ensures \result == 0;
- @
- @ also
- @
- @ requires this.value() > 0;
- @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
- @*/
- private /*@ pure @*/ int size() {
- return nWords + offset;
- }
-
-
- /**
- * Computes
- * <pre>
- * q = (int)( this / S )
- * this = 10 * ( this mod S )
- * Return q.
- * </pre>
- * This is the iteration step of digit development for output.
- * We assume that S has been normalized, as above, and that
- * "this" has been left-shifted accordingly.
- * Also assumed, of course, is that the result, q, can be expressed
- * as an integer, {@code 0 <= q < 10}.
- *
- * @param S The divisor of this <code>FDBigInteger</code>.
- * @return <code>q = (int)(this / S)</code>.
- */
- /*@
- @ requires !this.isImmutable;
- @ requires this.size() <= S.size();
- @ requires this.data.length + this.offset >= S.size();
- @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4);
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures \result == \old(this.value() / S.value());
- @ ensures this.value() == \old(10 * (this.value() % S.value()));
- @*/
- public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException {
- assert !this.isImmutable : "cannot modify immutable value";
- // ensure that this and S have the same number of
- // digits. If S is properly normalized and q < 10 then
- // this must be so.
- int thSize = this.size();
- int sSize = S.size();
- if (thSize < sSize) {
- // this value is significantly less than S, result of division is zero.
- // just mult this by 10.
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- if(p!=0) {
- this.data[nWords++] = p;
- } else {
- trimLeadingZeros();
- }
- return 0;
- } else if (thSize > sSize) {
- throw new IllegalArgumentException("disparate values");
- }
- // estimate q the obvious way. We will usually be
- // right. If not, then we're only off by a little and
- // will re-add.
- long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK);
- long diff = multDiffMe(q, S);
- if (diff != 0L) {
- //@ assert q != 0;
- //@ assert this.offset == \old(Math.min(this.offset, S.offset));
- //@ assert this.offset <= S.offset;
-
- // q is too big.
- // add S back in until this turns +. This should
- // not be very many times!
- long sum = 0L;
- int tStart = S.offset - this.offset;
- //@ assert tStart >= 0;
- int[] sd = S.data;
- int[] td = this.data;
- while (sum == 0L) {
- for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) {
- sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK);
- td[tIndex] = (int) sum;
- sum >>>= 32; // Signed or unsigned, answer is 0 or 1
- }
- //
- // Originally the following line read
- // "if ( sum !=0 && sum != -1 )"
- // but that would be wrong, because of the
- // treatment of the two values as entirely unsigned,
- // it would be impossible for a carry-out to be interpreted
- // as -1 -- it would have to be a single-bit carry-out, or +1.
- //
- assert sum == 0 || sum == 1 : sum; // carry out of division correction
- q -= 1;
- }
- }
- // finally, we can multiply this by 10.
- // it cannot overflow, right, as the high-order word has
- // at least 4 high-order zeros!
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- assert p == 0 : p; // Carry out of *10
- trimLeadingZeros();
- return (int) q;
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by 10. The operation will be
- * performed in place unless the <code>FDBigInteger</code> is immutable in
- * which case a new <code>FDBigInteger</code> will be returned.
- *
- * @return The <code>FDBigInteger</code> multiplied by 10.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && this.isImmutable;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * 10);
- @
- @ also
- @
- @ requires this.value() > 0 && !this.isImmutable;
- @ assignable this.nWords, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() * 10);
- @*/
- public FDBigInteger multBy10() {
- if (nWords == 0) {
- return this;
- }
- if (isImmutable) {
- int[] res = new int[nWords + 1];
- res[nWords] = multAndCarryBy10(data, nWords, res);
- return new FDBigInteger(res, offset);
- } else {
- int p = multAndCarryBy10(this.data, this.nWords, this.data);
- if (p != 0) {
- if (nWords == data.length) {
- if (data[0] == 0) {
- System.arraycopy(data, 1, data, 0, --nWords);
- offset++;
- } else {
- data = Arrays.copyOf(data, data.length + 1);
- }
- }
- data[nWords++] = p;
- } else {
- trimLeadingZeros();
- }
- return this;
- }
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>. The operation will be
- * performed in place if possible, otherwise a new <code>FDBigInteger</code>
- * will be returned.
- *
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return The multiplication result.
- */
- /*@
- @ requires this.value() == 0 || p5 == 0 && p2 == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable);
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
- @
- @ also
- @
- @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable;
- @ assignable this.nWords, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() * pow52(p5, p2));
- @*/
- public FDBigInteger multByPow52(int p5, int p2) {
- if (this.nWords == 0) {
- return this;
- }
- FDBigInteger res = this;
- if (p5 != 0) {
- int[] r;
- int extraSize = (p2 != 0) ? 1 : 0;
- if (p5 < SMALL_5_POW.length) {
- r = new int[this.nWords + 1 + extraSize];
- mult(this.data, this.nWords, SMALL_5_POW[p5], r);
- res = new FDBigInteger(r, this.offset);
- } else {
- FDBigInteger pow5 = big5pow(p5);
- r = new int[this.nWords + pow5.size() + extraSize];
- mult(this.data, this.nWords, pow5.data, pow5.nWords, r);
- res = new FDBigInteger(r, this.offset + pow5.offset);
- }
- }
- return res.leftShift(p2);
- }
-
- /**
- * Multiplies two big integers represented as int arrays.
- *
- * @param s1 The first array factor.
- * @param s1Len The number of elements of <code>s1</code> to use.
- * @param s2 The second array factor.
- * @param s2Len The number of elements of <code>s2</code> to use.
- * @param dst The product array.
- */
- /*@
- @ requires s1 != dst && s2 != dst;
- @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len;
- @ assignable dst[0 .. s1Len + s2Len - 1];
- @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len));
- @*/
- private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) {
- for (int i = 0; i < s1Len; i++) {
- long v = s1[i] & LONG_MASK;
- long p = 0L;
- for (int j = 0; j < s2Len; j++) {
- p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK);
- dst[i + j] = (int) p;
- p >>>= 32;
- }
- dst[i + s2Len] = (int) p;
- }
- }
-
- /**
- * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
- * <code>FDBigInteger</code>. Assert that the result is positive.
- * If the subtrahend is immutable, store the result in this(minuend).
- * If this(minuend) is immutable a new <code>FDBigInteger</code> is created.
- *
- * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
- * @return This <code>FDBigInteger</code> less the subtrahend.
- */
- /*@
- @ requires this.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @
- @ also
- @
- @ requires !subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures \result == this;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @*/
- public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) {
- assert this.size() >= subtrahend.size() : "result should be positive";
- FDBigInteger minuend;
- if (this.isImmutable) {
- minuend = new FDBigInteger(this.data.clone(), this.offset);
- } else {
- minuend = this;
- }
- int offsetDiff = subtrahend.offset - minuend.offset;
- int[] sData = subtrahend.data;
- int[] mData = minuend.data;
- int subLen = subtrahend.nWords;
- int minLen = minuend.nWords;
- if (offsetDiff < 0) {
- // need to expand minuend
- int rLen = minLen - offsetDiff;
- if (rLen < mData.length) {
- System.arraycopy(mData, 0, mData, -offsetDiff, minLen);
- Arrays.fill(mData, 0, -offsetDiff, 0);
- } else {
- int[] r = new int[rLen];
- System.arraycopy(mData, 0, r, -offsetDiff, minLen);
- minuend.data = mData = r;
- }
- minuend.offset = subtrahend.offset;
- minuend.nWords = minLen = rLen;
- offsetDiff = 0;
- }
- long borrow = 0L;
- int mIndex = offsetDiff;
- for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) {
- long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
- mData[mIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- for (; borrow != 0 && mIndex < minLen; mIndex++) {
- long diff = (mData[mIndex] & LONG_MASK) + borrow;
- mData[mIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- assert borrow == 0L : borrow; // borrow out of subtract,
- // result should be positive
- minuend.trimLeadingZeros();
- return minuend;
- }
-
- /**
- * Subtracts the supplied <code>FDBigInteger</code> subtrahend from this
- * <code>FDBigInteger</code>. Assert that the result is positive.
- * If the this(minuend) is immutable, store the result in subtrahend.
- * If subtrahend is immutable a new <code>FDBigInteger</code> is created.
- *
- * @param subtrahend The <code>FDBigInteger</code> to be subtracted.
- * @return This <code>FDBigInteger</code> less the subtrahend.
- */
- /*@
- @ requires subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @
- @ also
- @
- @ requires !subtrahend.isImmutable;
- @ requires this.value() >= subtrahend.value();
- @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*];
- @ ensures \result == subtrahend;
- @ ensures \result.value() == \old(this.value() - subtrahend.value());
- @*/
- public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) {
- assert this.size() >= subtrahend.size() : "result should be positive";
- FDBigInteger minuend = this;
- if (subtrahend.isImmutable) {
- subtrahend = new FDBigInteger(subtrahend.data.clone(), subtrahend.offset);
- }
- int offsetDiff = minuend.offset - subtrahend.offset;
- int[] sData = subtrahend.data;
- int[] mData = minuend.data;
- int subLen = subtrahend.nWords;
- int minLen = minuend.nWords;
- if (offsetDiff < 0) {
- int rLen = minLen;
- if (rLen < sData.length) {
- System.arraycopy(sData, 0, sData, -offsetDiff, subLen);
- Arrays.fill(sData, 0, -offsetDiff, 0);
- } else {
- int[] r = new int[rLen];
- System.arraycopy(sData, 0, r, -offsetDiff, subLen);
- subtrahend.data = sData = r;
- }
- subtrahend.offset = minuend.offset;
- subLen -= offsetDiff;
- offsetDiff = 0;
- } else {
- int rLen = minLen + offsetDiff;
- if (rLen >= sData.length) {
- subtrahend.data = sData = Arrays.copyOf(sData, rLen);
- }
- }
- //@ assert minuend == this && minuend.value() == \old(this.value());
- //@ assert mData == minuend.data && minLen == minuend.nWords;
- //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size();
- //@ assert sData == subtrahend.data;
- //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value());
- //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset);
- //@ assert offsetDiff == minuend.offset - subtrahend.offset;
- //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length;
- int sIndex = 0;
- long borrow = 0L;
- for (; sIndex < offsetDiff; sIndex++) {
- long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow;
- sData[sIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- //@ assert sIndex == offsetDiff;
- for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) {
- //@ assert sIndex == offsetDiff + mIndex;
- long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow;
- sData[sIndex] = (int) diff;
- borrow = diff >> 32; // signed shift
- }
- assert borrow == 0L : borrow; // borrow out of subtract,
- // result should be positive
- subtrahend.nWords = sIndex;
- subtrahend.trimLeadingZeros();
- return subtrahend;
-
- }
-
- /**
- * Determines whether all elements of an array are zero for all indices less
- * than a given index.
- *
- * @param a The array to be examined.
- * @param from The index strictly below which elements are to be examined.
- * @return Zero if all elements in range are zero, 1 otherwise.
- */
- /*@
- @ requires 0 <= from && from <= a.length;
- @ ensures \result == (AP(a, from) == 0 ? 0 : 1);
- @*/
- private /*@ pure @*/ static int checkZeroTail(int[] a, int from) {
- while (from > 0) {
- if (a[--from] != 0) {
- return 1;
- }
- }
- return 0;
- }
-
- /**
- * Compares the parameter with this <code>FDBigInteger</code>. Returns an
- * integer accordingly as:
- * <pre>{@code
- * > 0: this > other
- * 0: this == other
- * < 0: this < other
- * }</pre>
- *
- * @param other The <code>FDBigInteger</code> to compare.
- * @return A negative value, zero, or a positive value according to the
- * result of the comparison.
- */
- /*@
- @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0);
- @*/
- public /*@ pure @*/ int cmp(FDBigInteger other) {
- int aSize = nWords + offset;
- int bSize = other.nWords + other.offset;
- if (aSize > bSize) {
- return 1;
- } else if (aSize < bSize) {
- return -1;
- }
- int aLen = nWords;
- int bLen = other.nWords;
- while (aLen > 0 && bLen > 0) {
- int a = data[--aLen];
- int b = other.data[--bLen];
- if (a != b) {
- return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
- }
- }
- if (aLen > 0) {
- return checkZeroTail(data, aLen);
- }
- if (bLen > 0) {
- return -checkZeroTail(other.data, bLen);
- }
- return 0;
- }
-
- /**
- * Compares this <code>FDBigInteger</code> with
- * <code>5<sup>p5</sup> * 2<sup>p2</sup></code>.
- * Returns an integer accordingly as:
- * <pre>{@code
- * > 0: this > other
- * 0: this == other
- * < 0: this < other
- * }</pre>
- * @param p5 The exponent of the power-of-five factor.
- * @param p2 The exponent of the power-of-two factor.
- * @return A negative value, zero, or a positive value according to the
- * result of the comparison.
- */
- /*@
- @ requires p5 >= 0 && p2 >= 0;
- @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0);
- @*/
- public /*@ pure @*/ int cmpPow52(int p5, int p2) {
- if (p5 == 0) {
- int wordcount = p2 >> 5;
- int bitcount = p2 & 0x1f;
- int size = this.nWords + this.offset;
- if (size > wordcount + 1) {
- return 1;
- } else if (size < wordcount + 1) {
- return -1;
- }
- int a = this.data[this.nWords -1];
- int b = 1 << bitcount;
- if (a != b) {
- return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
- }
- return checkZeroTail(this.data, this.nWords - 1);
- }
- return this.cmp(big5pow(p5).leftShift(p2));
- }
-
- /**
- * Compares this <code>FDBigInteger</code> with <code>x + y</code>. Returns a
- * value according to the comparison as:
- * <pre>{@code
- * -1: this < x + y
- * 0: this == x + y
- * 1: this > x + y
- * }</pre>
- * @param x The first addend of the sum to compare.
- * @param y The second addend of the sum to compare.
- * @return -1, 0, or 1 according to the result of the comparison.
- */
- /*@
- @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0);
- @*/
- public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) {
- FDBigInteger big;
- FDBigInteger small;
- int xSize = x.size();
- int ySize = y.size();
- int bSize;
- int sSize;
- if (xSize >= ySize) {
- big = x;
- small = y;
- bSize = xSize;
- sSize = ySize;
- } else {
- big = y;
- small = x;
- bSize = ySize;
- sSize = xSize;
- }
- int thSize = this.size();
- if (bSize == 0) {
- return thSize == 0 ? 0 : 1;
- }
- if (sSize == 0) {
- return this.cmp(big);
- }
- if (bSize > thSize) {
- return -1;
- }
- if (bSize + 1 < thSize) {
- return 1;
- }
- long top = (big.data[big.nWords - 1] & LONG_MASK);
- if (sSize == bSize) {
- top += (small.data[small.nWords - 1] & LONG_MASK);
- }
- if ((top >>> 32) == 0) {
- if (((top + 1) >>> 32) == 0) {
- // good case - no carry extension
- if (bSize < thSize) {
- return 1;
- }
- // here sum.nWords == this.nWords
- long v = (this.data[this.nWords - 1] & LONG_MASK);
- if (v < top) {
- return -1;
- }
- if (v > top + 1) {
- return 1;
- }
- }
- } else { // (top>>>32)!=0 guaranteed carry extension
- if (bSize + 1 > thSize) {
- return -1;
- }
- // here sum.nWords == this.nWords
- top >>>= 32;
- long v = (this.data[this.nWords - 1] & LONG_MASK);
- if (v < top) {
- return -1;
- }
- if (v > top + 1) {
- return 1;
- }
- }
- return this.cmp(big.add(small));
- }
-
- /**
- * Makes this <code>FDBigInteger</code> immutable.
- */
- /*@
- @ assignable this.isImmutable;
- @ ensures this.isImmutable;
- @*/
- public void makeImmutable() {
- this.isImmutable = true;
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by an integer.
- *
- * @param i The factor by which to multiply this <code>FDBigInteger</code>.
- * @return This <code>FDBigInteger</code> multiplied by an integer.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() != 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * UNSIGNED(i));
- @*/
- private FDBigInteger mult(int i) {
- if (this.nWords == 0) {
- return this;
- }
- int[] r = new int[nWords + 1];
- mult(data, nWords, i, r);
- return new FDBigInteger(r, offset);
- }
-
- /**
- * Multiplies this <code>FDBigInteger</code> by another <code>FDBigInteger</code>.
- *
- * @param other The <code>FDBigInteger</code> factor by which to multiply.
- * @return The product of this and the parameter <code>FDBigInteger</code>s.
- */
- /*@
- @ requires this.value() == 0;
- @ assignable \nothing;
- @ ensures \result == this;
- @
- @ also
- @
- @ requires this.value() != 0 && other.value() == 0;
- @ assignable \nothing;
- @ ensures \result == other;
- @
- @ also
- @
- @ requires this.value() != 0 && other.value() != 0;
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() * other.value());
- @*/
- private FDBigInteger mult(FDBigInteger other) {
- if (this.nWords == 0) {
- return this;
- }
- if (this.size() == 1) {
- return other.mult(data[0]);
- }
- if (other.nWords == 0) {
- return other;
- }
- if (other.size() == 1) {
- return this.mult(other.data[0]);
- }
- int[] r = new int[nWords + other.nWords];
- mult(this.data, this.nWords, other.data, other.nWords, r);
- return new FDBigInteger(r, this.offset + other.offset);
- }
-
- /**
- * Adds another <code>FDBigInteger</code> to this <code>FDBigInteger</code>.
- *
- * @param other The <code>FDBigInteger</code> to add.
- * @return The sum of the <code>FDBigInteger</code>s.
- */
- /*@
- @ assignable \nothing;
- @ ensures \result.value() == \old(this.value() + other.value());
- @*/
- private FDBigInteger add(FDBigInteger other) {
- FDBigInteger big, small;
- int bigLen, smallLen;
- int tSize = this.size();
- int oSize = other.size();
- if (tSize >= oSize) {
- big = this;
- bigLen = tSize;
- small = other;
- smallLen = oSize;
- } else {
- big = other;
- bigLen = oSize;
- small = this;
- smallLen = tSize;
- }
- int[] r = new int[bigLen + 1];
- int i = 0;
- long carry = 0L;
- for (; i < smallLen; i++) {
- carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) )
- + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK)));
- r[i] = (int) carry;
- carry >>= 32; // signed shift.
- }
- for (; i < bigLen; i++) {
- carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) );
- r[i] = (int) carry;
- carry >>= 32; // signed shift.
- }
- r[bigLen] = (int) carry;
- return new FDBigInteger(r, 0);
- }
-
-
- /**
- * Multiplies a <code>FDBigInteger</code> by an int and adds another int. The
- * result is computed in place. This method is intended only to be invoked
- * from
- * <code>
- * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits)
- * </code>.
- *
- * @param iv The factor by which to multiply this <code>FDBigInteger</code>.
- * @param addend The value to add to the product of this
- * <code>FDBigInteger</code> and <code>iv</code>.
- */
- /*@
- @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32);
- @ assignable this.data[*];
- @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend));
- @*/
- private /*@ helper @*/ void multAddMe(int iv, int addend) {
- long v = iv & LONG_MASK;
- // unroll 0th iteration, doing addition.
- long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK);
- data[0] = (int) p;
- p >>>= 32;
- for (int i = 1; i < nWords; i++) {
- p += v * (data[i] & LONG_MASK);
- data[i] = (int) p;
- p >>>= 32;
- }
- if (p != 0L) {
- data[nWords++] = (int) p; // will fail noisily if illegal!
- }
- }
-
- //
- // original doc:
- //
- // do this -=q*S
- // returns borrow
- //
- /**
- * Multiplies the parameters and subtracts them from this
- * <code>FDBigInteger</code>.
- *
- * @param q The integer parameter.
- * @param S The <code>FDBigInteger</code> parameter.
- * @return <code>this - q*S</code>.
- */
- /*@
- @ ensures nWords == 0 ==> offset == 0;
- @ ensures nWords > 0 ==> data[nWords - 1] != 0;
- @*/
- /*@
- @ requires 0 < q && q <= (1L << 31);
- @ requires data != null;
- @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
- @ requires !this.isImmutable;
- @ requires this.size() == S.size();
- @ requires this != S;
- @ assignable this.nWords, this.offset, this.data, this.data[*];
- @ ensures -q <= \result && \result <= 0;
- @ ensures this.size() == \old(this.size());
- @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value());
- @ ensures this.offset == \old(Math.min(this.offset, S.offset));
- @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords);
- @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset);
- @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data);
- @
- @ also
- @
- @ requires q == 0;
- @ assignable \nothing;
- @ ensures \result == 0;
- @*/
- private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) {
- long diff = 0L;
- if (q != 0) {
- int deltaSize = S.offset - this.offset;
- if (deltaSize >= 0) {
- int[] sd = S.data;
- int[] td = this.data;
- for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) {
- diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
- td[tIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- } else {
- deltaSize = -deltaSize;
- int[] rd = new int[nWords + deltaSize];
- int sIndex = 0;
- int rIndex = 0;
- int[] sd = S.data;
- for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) {
- diff -= q * (sd[sIndex] & LONG_MASK);
- rd[rIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- int tIndex = 0;
- int[] td = this.data;
- for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) {
- diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK);
- rd[rIndex] = (int) diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- this.nWords += deltaSize;
- this.offset -= deltaSize;
- this.data = rd;
- }
- }
- return diff;
- }
-
-
- /**
- * Multiplies by 10 a big integer represented as an array. The final carry
- * is returned.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param dst The product array.
- * @return The final carry of the multiplication.
- */
- /*@
- @ requires src.length >= srcLen && dst.length >= srcLen;
- @ assignable dst[0 .. srcLen - 1];
- @ ensures 0 <= \result && \result < 10;
- @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10);
- @*/
- private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) {
- long carry = 0;
- for (int i = 0; i < srcLen; i++) {
- long product = (src[i] & LONG_MASK) * 10L + carry;
- dst[i] = (int) product;
- carry = product >>> 32;
- }
- return (int) carry;
- }
-
- /**
- * Multiplies by a constant value a big integer represented as an array.
- * The constant factor is an <code>int</code>.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param value The constant factor by which to multiply.
- * @param dst The product array.
- */
- /*@
- @ requires src.length >= srcLen && dst.length >= srcLen + 1;
- @ assignable dst[0 .. srcLen];
- @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value));
- @*/
- private static void mult(int[] src, int srcLen, int value, int[] dst) {
- long val = value & LONG_MASK;
- long carry = 0;
- for (int i = 0; i < srcLen; i++) {
- long product = (src[i] & LONG_MASK) * val + carry;
- dst[i] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen] = (int) carry;
- }
-
- /**
- * Multiplies by a constant value a big integer represented as an array.
- * The constant factor is a long represent as two <code>int</code>s.
- *
- * @param src The array representation of the big integer.
- * @param srcLen The number of elements of <code>src</code> to use.
- * @param v0 The lower 32 bits of the long factor.
- * @param v1 The upper 32 bits of the long factor.
- * @param dst The product array.
- */
- /*@
- @ requires src != dst;
- @ requires src.length >= srcLen && dst.length >= srcLen + 2;
- @ assignable dst[0 .. srcLen + 1];
- @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32)));
- @*/
- private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) {
- long v = v0 & LONG_MASK;
- long carry = 0;
- for (int j = 0; j < srcLen; j++) {
- long product = v * (src[j] & LONG_MASK) + carry;
- dst[j] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen] = (int) carry;
- v = v1 & LONG_MASK;
- carry = 0;
- for (int j = 0; j < srcLen; j++) {
- long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry;
- dst[j + 1] = (int) product;
- carry = product >>> 32;
- }
- dst[srcLen + 1] = (int) carry;
- }
-
- // Fails assertion for negative exponent.
- /**
- * Computes <code>5</code> raised to a given power.
- *
- * @param p The exponent of 5.
- * @return <code>5<sup>p</sup></code>.
- */
- private static FDBigInteger big5pow(int p) {
- assert p >= 0 : p; // negative power of 5
- if (p < MAX_FIVE_POW) {
- return POW_5_CACHE[p];
- }
- return big5powRec(p);
- }
-
- // slow path
- /**
- * Computes <code>5</code> raised to a given power.
- *
- * @param p The exponent of 5.
- * @return <code>5<sup>p</sup></code>.
- */
- private static FDBigInteger big5powRec(int p) {
- if (p < MAX_FIVE_POW) {
- return POW_5_CACHE[p];
- }
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- FDBigInteger bigq = big5powRec(q);
- if (r < SMALL_5_POW.length) {
- return bigq.mult(SMALL_5_POW[r]);
- } else {
- return bigq.mult(big5powRec(r));
- }
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a hexadecimal string.
- *
- * @return The hexadecimal string representation.
- */
- public String toHexString(){
- if(nWords ==0) {
- return "0";
- }
- StringBuilder sb = new StringBuilder((nWords +offset)*8);
- for(int i= nWords -1; i>=0; i--) {
- String subStr = Integer.toHexString(data[i]);
- for(int j = subStr.length(); j<8; j++) {
- sb.append('0');
- }
- sb.append(subStr);
- }
- for(int i=offset; i>0; i--) {
- sb.append("00000000");
- }
- return sb.toString();
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a <code>BigInteger</code>.
- *
- * @return The <code>BigInteger</code> representation.
- */
- public BigInteger toBigInteger() {
- byte[] magnitude = new byte[nWords * 4 + 1];
- for (int i = 0; i < nWords; i++) {
- int w = data[i];
- magnitude[magnitude.length - 4 * i - 1] = (byte) w;
- magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8);
- magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16);
- magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24);
- }
- return new BigInteger(magnitude).shiftLeft(offset * 32);
- }
-
- // for debugging ...
- /**
- * Converts this <code>FDBigInteger</code> to a string.
- *
- * @return The string representation.
- */
- @Override
- public String toString(){
- return toBigInteger().toString();
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FloatConsts.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2003, 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. 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.misc;
-
-/**
- * This class contains additional constants documenting limits of the
- * <code>float</code> type.
- *
- * @author Joseph D. Darcy
- */
-
-public class FloatConsts {
- /**
- * Don't let anyone instantiate this class.
- */
- private FloatConsts() {}
-
- public static final float POSITIVE_INFINITY = java.lang.Float.POSITIVE_INFINITY;
- public static final float NEGATIVE_INFINITY = java.lang.Float.NEGATIVE_INFINITY;
- public static final float NaN = java.lang.Float.NaN;
- public static final float MAX_VALUE = java.lang.Float.MAX_VALUE;
- public static final float MIN_VALUE = java.lang.Float.MIN_VALUE;
-
- /**
- * A constant holding the smallest positive normal value of type
- * <code>float</code>, 2<sup>-126</sup>. It is equal to the value
- * returned by <code>Float.intBitsToFloat(0x00800000)</code>.
- */
- public static final float MIN_NORMAL = 1.17549435E-38f;
-
- /**
- * The number of logical bits in the significand of a
- * <code>float</code> number, including the implicit bit.
- */
- public static final int SIGNIFICAND_WIDTH = 24;
-
- /**
- * Maximum exponent a finite <code>float</code> number may have.
- * It is equal to the value returned by
- * <code>Math.ilogb(Float.MAX_VALUE)</code>.
- */
- public static final int MAX_EXPONENT = 127;
-
- /**
- * Minimum exponent a normalized <code>float</code> number may
- * have. It is equal to the value returned by
- * <code>Math.ilogb(Float.MIN_NORMAL)</code>.
- */
- public static final int MIN_EXPONENT = -126;
-
- /**
- * The exponent the smallest positive <code>float</code> subnormal
- * value would have if it could be normalized.
- */
- public static final int MIN_SUB_EXPONENT = MIN_EXPONENT -
- (SIGNIFICAND_WIDTH - 1);
-
- /**
- * Bias used in representing a <code>float</code> exponent.
- */
- public static final int EXP_BIAS = 127;
-
- /**
- * Bit mask to isolate the sign bit of a <code>float</code>.
- */
- public static final int SIGN_BIT_MASK = 0x80000000;
-
- /**
- * Bit mask to isolate the exponent field of a
- * <code>float</code>.
- */
- public static final int EXP_BIT_MASK = 0x7F800000;
-
- /**
- * Bit mask to isolate the significand field of a
- * <code>float</code>.
- */
- public static final int SIGNIF_BIT_MASK = 0x007FFFFF;
-
- static {
- // verify bit masks cover all bit positions and that the bit
- // masks are non-overlapping
- assert(((SIGN_BIT_MASK | EXP_BIT_MASK | SIGNIF_BIT_MASK) == ~0) &&
- (((SIGN_BIT_MASK & EXP_BIT_MASK) == 0) &&
- ((SIGN_BIT_MASK & SIGNIF_BIT_MASK) == 0) &&
- ((EXP_BIT_MASK & SIGNIF_BIT_MASK) == 0)));
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FloatingDecimal.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2552 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-import java.util.Arrays;
-import java.util.regex.*;
-
-/**
- * A class for converting between ASCII and decimal representations of a single
- * or double precision floating point number. Most conversions are provided via
- * static convenience methods, although a <code>BinaryToASCIIConverter</code>
- * instance may be obtained and reused.
- */
-public class FloatingDecimal{
- //
- // Constants of the implementation;
- // most are IEEE-754 related.
- // (There are more really boring constants at the end.)
- //
- static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1;
- static final long FRACT_HOB = ( 1L<<EXP_SHIFT ); // assumed High-Order bit
- static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
- static final int MAX_SMALL_BIN_EXP = 62;
- static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
- static final int MAX_DECIMAL_DIGITS = 15;
- static final int MAX_DECIMAL_EXPONENT = 308;
- static final int MIN_DECIMAL_EXPONENT = -324;
- static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
- static final int MAX_NDIGITS = 1100;
-
- static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
- static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
- static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
- static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
- static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
- static final int SINGLE_MAX_NDIGITS = 200;
-
- static final int INT_DECIMAL_DIGITS = 9;
-
- /**
- * Converts a double precision floating point value to a <code>String</code>.
- *
- * @param d The double precision value.
- * @return The value converted to a <code>String</code>.
- */
- public static String toJavaFormatString(double d) {
- return getBinaryToASCIIConverter(d).toJavaFormatString();
- }
-
- /**
- * Converts a single precision floating point value to a <code>String</code>.
- *
- * @param f The single precision value.
- * @return The value converted to a <code>String</code>.
- */
- public static String toJavaFormatString(float f) {
- return getBinaryToASCIIConverter(f).toJavaFormatString();
- }
-
- /**
- * Appends a double precision floating point value to an <code>Appendable</code>.
- * @param d The double precision value.
- * @param buf The <code>Appendable</code> with the value appended.
- */
- public static void appendTo(double d, Appendable buf) {
- getBinaryToASCIIConverter(d).appendTo(buf);
- }
-
- /**
- * Appends a single precision floating point value to an <code>Appendable</code>.
- * @param f The single precision value.
- * @param buf The <code>Appendable</code> with the value appended.
- */
- public static void appendTo(float f, Appendable buf) {
- getBinaryToASCIIConverter(f).appendTo(buf);
- }
-
- /**
- * Converts a <code>String</code> to a double precision floating point value.
- *
- * @param s The <code>String</code> to convert.
- * @return The double precision value.
- * @throws NumberFormatException If the <code>String</code> does not
- * represent a properly formatted double precision value.
- */
- public static double parseDouble(String s) throws NumberFormatException {
- return readJavaFormatString(s).doubleValue();
- }
-
- /**
- * Converts a <code>String</code> to a single precision floating point value.
- *
- * @param s The <code>String</code> to convert.
- * @return The single precision value.
- * @throws NumberFormatException If the <code>String</code> does not
- * represent a properly formatted single precision value.
- */
- public static float parseFloat(String s) throws NumberFormatException {
- return readJavaFormatString(s).floatValue();
- }
-
- /**
- * A converter which can process single or double precision floating point
- * values into an ASCII <code>String</code> representation.
- */
- public interface BinaryToASCIIConverter {
- /**
- * Converts a floating point value into an ASCII <code>String</code>.
- * @return The value converted to a <code>String</code>.
- */
- public String toJavaFormatString();
-
- /**
- * Appends a floating point value to an <code>Appendable</code>.
- * @param buf The <code>Appendable</code> to receive the value.
- */
- public void appendTo(Appendable buf);
-
- /**
- * Retrieves the decimal exponent most closely corresponding to this value.
- * @return The decimal exponent.
- */
- public int getDecimalExponent();
-
- /**
- * Retrieves the value as an array of digits.
- * @param digits The digit array.
- * @return The number of valid digits copied into the array.
- */
- public int getDigits(char[] digits);
-
- /**
- * Indicates the sign of the value.
- * @return {@code value < 0.0}.
- */
- public boolean isNegative();
-
- /**
- * Indicates whether the value is either infinite or not a number.
- *
- * @return <code>true</code> if and only if the value is <code>NaN</code>
- * or infinite.
- */
- public boolean isExceptional();
-
- /**
- * Indicates whether the value was rounded up during the binary to ASCII
- * conversion.
- *
- * @return <code>true</code> if and only if the value was rounded up.
- */
- public boolean digitsRoundedUp();
-
- /**
- * Indicates whether the binary to ASCII conversion was exact.
- *
- * @return <code>true</code> if any only if the conversion was exact.
- */
- public boolean decimalDigitsExact();
- }
-
- /**
- * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
- * and infinite values.
- */
- private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
- private final String image;
- private boolean isNegative;
-
- public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
- this.image = image;
- this.isNegative = isNegative;
- }
-
- @Override
- public String toJavaFormatString() {
- return image;
- }
-
- @Override
- public void appendTo(Appendable buf) {
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(image);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(image);
- } else {
- assert false;
- }
- }
-
- @Override
- public int getDecimalExponent() {
- throw new IllegalArgumentException("Exceptional value does not have an exponent");
- }
-
- @Override
- public int getDigits(char[] digits) {
- throw new IllegalArgumentException("Exceptional value does not have digits");
- }
-
- @Override
- public boolean isNegative() {
- return isNegative;
- }
-
- @Override
- public boolean isExceptional() {
- return true;
- }
-
- @Override
- public boolean digitsRoundedUp() {
- throw new IllegalArgumentException("Exceptional value is not rounded");
- }
-
- @Override
- public boolean decimalDigitsExact() {
- throw new IllegalArgumentException("Exceptional value is not exact");
- }
- }
-
- private static final String INFINITY_REP = "Infinity";
- private static final int INFINITY_LENGTH = INFINITY_REP.length();
- private static final String NAN_REP = "NaN";
- private static final int NAN_LENGTH = NAN_REP.length();
-
- private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false);
- private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true);
- private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false);
- private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'});
- private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'});
-
- /**
- * A buffered implementation of <code>BinaryToASCIIConverter</code>.
- */
- static class BinaryToASCIIBuffer implements BinaryToASCIIConverter {
- private boolean isNegative;
- private int decExponent;
- private int firstDigitIndex;
- private int nDigits;
- private final char[] digits;
- private final char[] buffer = new char[26];
-
- //
- // The fields below provide additional information about the result of
- // the binary to decimal digits conversion done in dtoa() and roundup()
- // methods. They are changed if needed by those two methods.
- //
-
- // True if the dtoa() binary to decimal conversion was exact.
- private boolean exactDecimalConversion = false;
-
- // True if the result of the binary to decimal conversion was rounded-up
- // at the end of the conversion process, i.e. roundUp() method was called.
- private boolean decimalDigitsRoundedUp = false;
-
- /**
- * Default constructor; used for non-zero values,
- * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
- */
- BinaryToASCIIBuffer(){
- this.digits = new char[20];
- }
-
- /**
- * Creates a specialized value (positive and negative zeros).
- */
- BinaryToASCIIBuffer(boolean isNegative, char[] digits){
- this.isNegative = isNegative;
- this.decExponent = 0;
- this.digits = digits;
- this.firstDigitIndex = 0;
- this.nDigits = digits.length;
- }
-
- @Override
- public String toJavaFormatString() {
- int len = getChars(buffer);
- return new String(buffer, 0, len);
- }
-
- @Override
- public void appendTo(Appendable buf) {
- int len = getChars(buffer);
- if (buf instanceof StringBuilder) {
- ((StringBuilder) buf).append(buffer, 0, len);
- } else if (buf instanceof StringBuffer) {
- ((StringBuffer) buf).append(buffer, 0, len);
- } else {
- assert false;
- }
- }
-
- @Override
- public int getDecimalExponent() {
- return decExponent;
- }
-
- @Override
- public int getDigits(char[] digits) {
- System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
- return this.nDigits;
- }
-
- @Override
- public boolean isNegative() {
- return isNegative;
- }
-
- @Override
- public boolean isExceptional() {
- return false;
- }
-
- @Override
- public boolean digitsRoundedUp() {
- return decimalDigitsRoundedUp;
- }
-
- @Override
- public boolean decimalDigitsExact() {
- return exactDecimalConversion;
- }
-
- private void setSign(boolean isNegative) {
- this.isNegative = isNegative;
- }
-
- /**
- * This is the easy subcase --
- * all the significant bits, after scaling, are held in lvalue.
- * negSign and decExponent tell us what processing and scaling
- * has already been done. Exceptional cases have already been
- * stripped out.
- * In particular:
- * lvalue is a finite number (not Inf, nor NaN)
- * lvalue > 0L (not zero, nor negative).
- *
- * The only reason that we develop the digits here, rather than
- * calling on Long.toString() is that we can do it a little faster,
- * and besides want to treat trailing 0s specially. If Long.toString
- * changes, we should re-evaluate this strategy!
- */
- private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){
- if ( insignificantDigits != 0 ){
- // Discard non-significant low-order bits, while rounding,
- // up to insignificant value.
- long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i;
- long residue = lvalue % pow10;
- lvalue /= pow10;
- decExponent += insignificantDigits;
- if ( residue >= (pow10>>1) ){
- // round up based on the low-order bits we're discarding
- lvalue++;
- }
- }
- int digitno = digits.length -1;
- int c;
- if ( lvalue <= Integer.MAX_VALUE ){
- assert lvalue > 0L : lvalue; // lvalue <= 0
- // even easier subcase!
- // can do int arithmetic rather than long!
- int ivalue = (int)lvalue;
- c = ivalue%10;
- ivalue /= 10;
- while ( c == 0 ){
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- } else {
- // same algorithm as above (same bugs, too )
- // but using long arithmetic.
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- while ( c == 0 ){
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- }
- while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- }
- this.decExponent = decExponent+1;
- this.firstDigitIndex = digitno;
- this.nDigits = this.digits.length - digitno;
- }
-
- private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat)
- {
- assert fractBits > 0 ; // fractBits here can't be zero or negative
- assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- final int tailZeros = Long.numberOfTrailingZeros(fractBits);
-
- // number of significant bits of fractBits;
- final int nFractBits = EXP_SHIFT+1-tailZeros;
-
- // reset flags to default values as dtoa() does not always set these
- // flags and a prior call to dtoa() might have set them to incorrect
- // values with respect to the current state.
- decimalDigitsRoundedUp = false;
- exactDecimalConversion = false;
-
- // number of significant bits to the right of the point.
- int nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){
- //
- // We can do this:
- // take the fraction bits, which are normalized.
- // (a) nTinyBits == 0: Shift left or right appropriately
- // to align the binary point at the extreme right, i.e.
- // where a long int point is expected to be. The integer
- // result is easily converted to a string.
- // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits,
- // which effectively converts to long and scales by
- // 2^nTinyBits. Then multiply by 5^nTinyBits to
- // complete the scaling. We know this won't overflow
- // because we just counted the number of bits necessary
- // in the result. The integer you get from this can
- // then be converted to a string pretty easily.
- //
- if ( nTinyBits == 0 ) {
- int insignificant;
- if ( binExp > nSignificantBits ){
- insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1);
- } else {
- insignificant = 0;
- }
- if ( binExp >= EXP_SHIFT ){
- fractBits <<= (binExp-EXP_SHIFT);
- } else {
- fractBits >>>= (EXP_SHIFT-binExp) ;
- }
- developLongDigits( 0, fractBits, insignificant );
- return;
- }
- //
- // The following causes excess digits to be printed
- // out in the single-float case. Our manipulation of
- // halfULP here is apparently not correct. If we
- // better understand how this works, perhaps we can
- // use this special case again. But for the time being,
- // we do not.
- // else {
- // fractBits >>>= EXP_SHIFT+1-nFractBits;
- // fractBits//= long5pow[ nTinyBits ];
- // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) );
- // return;
- // }
- //
- }
- }
- //
- // This is the hard case. We are going to compute large positive
- // integers B and S and integer decExp, s.t.
- // d = ( B / S )// 10^decExp
- // 1 <= B / S < 10
- // Obvious choices are:
- // decExp = floor( log10(d) )
- // B = d// 2^nTinyBits// 10^max( 0, -decExp )
- // S = 10^max( 0, decExp)// 2^nTinyBits
- // (noting that nTinyBits has already been forced to non-negative)
- // I am also going to compute a large positive integer
- // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp )
- // i.e. M is (1/2) of the ULP of d, scaled like B.
- // When we iterate through dividing B/S and picking off the
- // quotient bits, we will know when to stop when the remainder
- // is <= M.
- //
- // We keep track of powers of 2 and powers of 5.
- //
- int decExp = estimateDecExp(fractBits,binExp);
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- //
- // the long integer fractBits contains the (nFractBits) interesting
- // bits from the mantissa of d ( hidden 1 added if necessary) followed
- // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness,
- // I will shift out those zeros before turning fractBits into a
- // FDBigInteger. The resulting whole number will be
- // d * 2^(nFractBits-1-binExp).
- //
- fractBits >>>= tailZeros;
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- //
- // HACK!! For exact powers of two, the next smallest number
- // is only half as far away as we think (because the meaning of
- // ULP changes at power-of-two bounds) for this reason, we
- // hack M2. Hope this works.
- //
- if ( nFractBits == 1 ) {
- M2 -= 1;
- }
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- //
- // Construct, Scale, iterate.
- // Some day, we'll write a stopping test that takes
- // account of the asymmetry of the spacing of floating-point
- // numbers below perfect powers of 2
- // 26 Sept 96 is not that day.
- // So we use a symmetric test.
- //
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- //
- // Detect the special cases where all the numbers we are about
- // to compute will fit in int or long integers.
- // In these cases, we will avoid doing FDBigInteger arithmetic.
- // We use the same algorithms, except that we "normalize"
- // our FDBigIntegers before iterating. This is to make division easier,
- // as it makes our fist guess (quotient of high-order words)
- // more accurate!
- //
- // Some day, we'll write a stopping test that takes
- // account of the asymmetry of the spacing of floating-point
- // numbers below perfect powers of 2
- // 26 Sept 96 is not that day.
- // So we use a symmetric test.
- //
- // binary digits needed to represent B, approx.
- int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 ));
-
- // binary digits needed to represent 10*S, approx.
- int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2;
- int s = FDBigInteger.SMALL_5_POW[S5] << S2;
- int m = FDBigInteger.SMALL_5_POW[M5] << M2;
- int tens = s * 10;
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- } else {
- // still good! they're all longs!
- long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2;
- long s = FDBigInteger.LONG_5_POW[S5] << S2;
- long m = FDBigInteger.LONG_5_POW[M5] << M2;
- long tens = s * 10L;
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- }
- } else {
- //
- // We really must do FDBigInteger arithmetic.
- // Fist, construct our FDBigInteger initial values.
- //
- FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2);
- int shiftBias = Sval.getNormalizationBias();
- Sval = Sval.leftShift(shiftBias); // normalize so that division works better
-
- FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias);
- FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1);
-
- FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 );
- //
- // Unroll the first iteration. If our decExp estimate
- // was too high, our first quotient will be zero. In this
- // case, we discard it and decrement decExp.
- //
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- low = (Bval.cmp( Mval ) < 0);
- high = tenSval.addAndCmp(Bval,Mval)<=0;
-
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- //
- // HACK! Java spec sez that we always have at least
- // one digit after the . in either F- or E-form output.
- // Thus we will need more than one digit if we're using
- // E-form
- //
- if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- assert q < 10 : q; // excessively large digit
- Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = tenSval.addAndCmp(Bval,Mval)<=0;
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval = Bval.leftShift(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else {
- lowDigitDifference = 0L; // this here only for flow analysis!
- }
- exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0);
- }
- this.decExponent = decExp+1;
- this.firstDigitIndex = 0;
- this.nDigits = ndigit;
- //
- // Last digit gets rounded based on stopping condition.
- //
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) {
- roundup();
- }
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- // add one to the least significant digit.
- // in the unlikely event there is a carry out, deal with it.
- // assert that this will only happen where there
- // is only one digit, e.g. (float)1e-44 seems to do it.
- //
- private void roundup() {
- int i = (firstDigitIndex + nDigits - 1);
- int q = digits[i];
- if (q == '9') {
- while (q == '9' && i > firstDigitIndex) {
- digits[i] = '0';
- q = digits[--i];
- }
- if (q == '9') {
- // carryout! High-order 1, rest 0s, larger exp.
- decExponent += 1;
- digits[firstDigitIndex] = '1';
- return;
- }
- // else fall through.
- }
- digits[i] = (char) (q + 1);
- decimalDigitsRoundedUp = true;
- }
-
- /**
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- */
- static int estimateDecExp(long fractBits, int binExp) {
- double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) );
- double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981;
- long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw
- int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS;
- boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
- if(exponent>=0 && exponent<52) { // hot path
- long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent;
- int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent));
- return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r;
- } else if (exponent < 0) {
- return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 :
- ( (isNegative) ? -1 : 0) );
- } else { //if (exponent >= 52)
- return (int)d;
- }
- }
-
- private static int insignificantDigits(int insignificant) {
- int i;
- for ( i = 0; insignificant >= 10L; i++ ) {
- insignificant /= 10L;
- }
- return i;
- }
-
- /**
- * Calculates
- * <pre>
- * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
- * </pre>
- */
- private static int insignificantDigitsForPow2(int p2) {
- if(p2>1 && p2 < insignificantDigitsNumber.length) {
- return insignificantDigitsNumber[p2];
- }
- return 0;
- }
-
- /**
- * If insignificant==(1L << ixd)
- * i = insignificantDigitsNumber[idx] is the same as:
- * int i;
- * for ( i = 0; insignificant >= 10L; i++ )
- * insignificant /= 10L;
- */
- private static int[] insignificantDigitsNumber = {
- 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
- 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
- 12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
- 15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
- 18, 18, 18, 19
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int[] N_5_BITS = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) {
- result[0] = '-';
- i = 1;
- }
- if (decExponent > 0 && decExponent < 8) {
- // print digits.digits.
- int charLength = Math.min(nDigits, decExponent);
- System.arraycopy(digits, firstDigitIndex, result, i, charLength);
- i += charLength;
- if (charLength < decExponent) {
- charLength = decExponent - charLength;
- Arrays.fill(result,i,i+charLength,'0');
- i += charLength;
- result[i++] = '.';
- result[i++] = '0';
- } else {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = nDigits - charLength;
- System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- }
- } else if (decExponent <= 0 && decExponent > -3) {
- result[i++] = '0';
- result[i++] = '.';
- if (decExponent != 0) {
- Arrays.fill(result, i, i-decExponent, '0');
- i -= decExponent;
- }
- System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
- i += nDigits;
- } else {
- result[i++] = digits[firstDigitIndex];
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
- i += nDigits - 1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- int e;
- if (decExponent <= 0) {
- result[i++] = '-';
- e = -decExponent + 1;
- } else {
- e = decExponent - 1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- result[i++] = (char) (e + '0');
- } else if (e <= 99) {
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
- } else {
- result[i++] = (char) (e / 100 + '0');
- e %= 100;
- result[i++] = (char) (e / 10 + '0');
- result[i++] = (char) (e % 10 + '0');
- }
- }
- return i;
- }
-
- }
-
- private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
- new ThreadLocal<BinaryToASCIIBuffer>() {
- @Override
- protected BinaryToASCIIBuffer initialValue() {
- return new BinaryToASCIIBuffer();
- }
- };
-
- private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
- return threadLocalBinaryToASCIIBuffer.get();
- }
-
- /**
- * A converter which can process an ASCII <code>String</code> representation
- * of a single or double precision floating point value into a
- * <code>float</code> or a <code>double</code>.
- */
- interface ASCIIToBinaryConverter {
-
- double doubleValue();
-
- float floatValue();
-
- }
-
- /**
- * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
- */
- static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
- private final double doubleVal;
- private final float floatVal;
-
- public PreparedASCIIToBinaryBuffer(double doubleVal, float floatVal) {
- this.doubleVal = doubleVal;
- this.floatVal = floatVal;
- }
-
- @Override
- public double doubleValue() {
- return doubleVal;
- }
-
- @Override
- public float floatValue() {
- return floatVal;
- }
- }
-
- static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY, Float.POSITIVE_INFINITY);
- static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY);
- static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER = new PreparedASCIIToBinaryBuffer(Double.NaN, Float.NaN);
- static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d, 0.0f);
- static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d, -0.0f);
-
- /**
- * A buffered implementation of <code>ASCIIToBinaryConverter</code>.
- */
- static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
- boolean isNegative;
- int decExponent;
- char digits[];
- int nDigits;
-
- ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
- {
- this.isNegative = negSign;
- this.decExponent = decExponent;
- this.digits = digits;
- this.nDigits = n;
- }
-
- /**
- * Takes a FloatingDecimal, which we presumably just scanned in,
- * and finds out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
- */
- @Override
- public double doubleValue() {
- int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
- //
- // convert the lead kDigits to a long integer.
- //
- // (special performance hack: start to do it using int)
- int iValue = (int) digits[0] - (int) '0';
- int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
- for (int i = 1; i < iDigits; i++) {
- iValue = iValue * 10 + (int) digits[i] - (int) '0';
- }
- long lValue = (long) iValue;
- for (int i = iDigits; i < kDigits; i++) {
- lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
- }
- double dValue = (double) lValue;
- int exp = decExponent - kDigits;
- //
- // lValue now contains a long integer with the value of
- // the first kDigits digits of the number.
- // dValue contains the (double) of the same.
- //
-
- if (nDigits <= MAX_DECIMAL_DIGITS) {
- //
- // possibly an easy case.
- // We know that the digits can be represented
- // exactly. And if the exponent isn't too outrageous,
- // the whole thing can be done with one operation,
- // thus one rounding error.
- // Note that all our constructors trim all leading and
- // trailing zeros, so simple values (including zero)
- // will always end up here
- //
- if (exp == 0 || dValue == 0.0) {
- return (isNegative) ? -dValue : dValue; // small floating integer
- }
- else if (exp >= 0) {
- if (exp <= MAX_SMALL_TEN) {
- //
- // Can get the answer with one operation,
- // thus one roundoff.
- //
- double rValue = dValue * SMALL_10_POW[exp];
- return (isNegative) ? -rValue : rValue;
- }
- int slop = MAX_DECIMAL_DIGITS - kDigits;
- if (exp <= MAX_SMALL_TEN + slop) {
- //
- // We can multiply dValue by 10^(slop)
- // and it is still "small" and exact.
- // Then we can multiply by 10^(exp-slop)
- // with one rounding.
- //
- dValue *= SMALL_10_POW[slop];
- double rValue = dValue * SMALL_10_POW[exp - slop];
- return (isNegative) ? -rValue : rValue;
- }
- //
- // Else we have a hard case with a positive exp.
- //
- } else {
- if (exp >= -MAX_SMALL_TEN) {
- //
- // Can get the answer in one division.
- //
- double rValue = dValue / SMALL_10_POW[-exp];
- return (isNegative) ? -rValue : rValue;
- }
- //
- // Else we have a hard case with a negative exp.
- //
- }
- }
-
- //
- // Harder cases:
- // The sum of digits plus exponent is greater than
- // what we think we can do with one error.
- //
- // Start by approximating the right answer by,
- // naively, scaling by powers of 10.
- //
- if (exp > 0) {
- if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
- //
- // Lets face it. This is going to be
- // Infinity. Cut to the chase.
- //
- return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ((exp & 15) != 0) {
- dValue *= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 1; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= BIG_10_POW[j];
- }
- }
- //
- // The reason for the weird exp > 1 condition
- // in the above loop was so that the last multiply
- // would get unrolled. We handle it here.
- // It could overflow.
- //
- double t = dValue * BIG_10_POW[j];
- if (Double.isInfinite(t)) {
- //
- // It did overflow.
- // Look more closely at the result.
- // If the exponent is just one too large,
- // then use the maximum finite as our estimate
- // value. Else call the result infinity
- // and punt it.
- // ( I presume this could happen because
- // rounding forces the result here to be
- // an ULP or two larger than
- // Double.MAX_VALUE ).
- //
- t = dValue / 2.0;
- t *= BIG_10_POW[j];
- if (Double.isInfinite(t)) {
- return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if (exp < 0) {
- exp = -exp;
- if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
- //
- // Lets face it. This is going to be
- // zero. Cut to the chase.
- //
- return (isNegative) ? -0.0 : 0.0;
- }
- if ((exp & 15) != 0) {
- dValue /= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 1; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= TINY_10_POW[j];
- }
- }
- //
- // The reason for the weird exp > 1 condition
- // in the above loop was so that the last multiply
- // would get unrolled. We handle it here.
- // It could underflow.
- //
- double t = dValue * TINY_10_POW[j];
- if (t == 0.0) {
- //
- // It did underflow.
- // Look more closely at the result.
- // If the exponent is just one too small,
- // then use the minimum finite as our estimate
- // value. Else call the result 0.0
- // and punt it.
- // ( I presume this could happen because
- // rounding forces the result here to be
- // an ULP or two less than
- // Double.MIN_VALUE ).
- //
- t = dValue * 2.0;
- t *= TINY_10_POW[j];
- if (t == 0.0) {
- return (isNegative) ? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- //
- // dValue is now approximately the result.
- // The hard part is adjusting it, by comparison
- // with FDBigInteger arithmetic.
- // Formulate the EXACT big-number result as
- // bigD0 * 10^exp
- //
- if (nDigits > MAX_NDIGITS) {
- nDigits = MAX_NDIGITS + 1;
- digits[MAX_NDIGITS] = '1';
- }
- FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
- exp = decExponent - nDigits;
-
- long ieeeBits = Double.doubleToRawLongBits(dValue); // IEEE-754 bits of double candidate
- final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
- final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
- bigD0 = bigD0.multByPow52(D5, 0);
- bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
- FDBigInteger bigD = null;
- int prevD2 = 0;
-
- correctionLoop:
- while (true) {
- // here ieeeBits can't be NaN, Infinity or zero
- int binexp = (int) (ieeeBits >>> EXP_SHIFT);
- long bigBbits = ieeeBits & DoubleConsts.SIGNIF_BIT_MASK;
- if (binexp > 0) {
- bigBbits |= FRACT_HOB;
- } else { // Normalize denormalized numbers.
- assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
- int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
- int shift = leadingZeros - (63 - EXP_SHIFT);
- bigBbits <<= shift;
- binexp = 1 - shift;
- }
- binexp -= DoubleConsts.EXP_BIAS;
- int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
- bigBbits >>>= lowOrderZeros;
- final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
- final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
-
- //
- // Scale bigD, bigB appropriately for
- // big-integer operations.
- // Naively, we multiply by powers of ten
- // and powers of two. What we actually do
- // is keep track of the powers of 5 and
- // powers of 2 we would use, then factor out
- // common divisors before doing the work.
- //
- int B2 = B5; // powers of 2 in bigB
- int D2 = D5; // powers of 2 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if (bigIntExp >= 0) {
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if (binexp <= -DoubleConsts.EXP_BIAS) {
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(DoubleConsts.EXP_BIAS+EXP_SHIFT+1)
- hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
- } else {
- hulpbias = 1 + lowOrderZeros;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min(B2, Math.min(D2, Ulp2));
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
- if (bigD == null || prevD2 != D2) {
- bigD = bigD0.leftShift(D2);
- prevD2 = D2;
- }
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInteger diff;
- int cmpResult;
- boolean overvalue;
- if ((cmpResult = bigB.cmp(bigD)) > 0) {
- overvalue = true; // our candidate is too big.
- diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
- if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
- // candidate is a normalized exact power of 2 and
- // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if (Ulp2 < 0) {
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff = diff.leftShift(1);
- }
- }
- } else if (cmpResult < 0) {
- overvalue = false; // our candidate is too small.
- diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- cmpResult = diff.cmpPow52(B5, Ulp2);
- if ((cmpResult) < 0) {
- // difference is small.
- // this is close enough
- break correctionLoop;
- } else if (cmpResult == 0) {
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- if ((ieeeBits & 1) != 0) { // half ties to even
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- if (ieeeBits == 0 || ieeeBits == DoubleConsts.EXP_BIT_MASK) { // 0.0 or Double.POSITIVE_INFINITY
- break correctionLoop; // oops. Fell off end of range.
- }
- continue; // try again.
- }
-
- }
- if (isNegative) {
- ieeeBits |= DoubleConsts.SIGN_BIT_MASK;
- }
- return Double.longBitsToDouble(ieeeBits);
- }
-
- /**
- * Takes a FloatingDecimal, which we presumably just scanned in,
- * and finds out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the conversion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
- */
- @Override
- public float floatValue() {
- int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
- //
- // convert the lead kDigits to an integer.
- //
- int iValue = (int) digits[0] - (int) '0';
- for (int i = 1; i < kDigits; i++) {
- iValue = iValue * 10 + (int) digits[i] - (int) '0';
- }
- float fValue = (float) iValue;
- int exp = decExponent - kDigits;
- //
- // iValue now contains an integer with the value of
- // the first kDigits digits of the number.
- // fValue contains the (float) of the same.
- //
-
- if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
- //
- // possibly an easy case.
- // We know that the digits can be represented
- // exactly. And if the exponent isn't too outrageous,
- // the whole thing can be done with one operation,
- // thus one rounding error.
- // Note that all our constructors trim all leading and
- // trailing zeros, so simple values (including zero)
- // will always end up here.
- //
- if (exp == 0 || fValue == 0.0f) {
- return (isNegative) ? -fValue : fValue; // small floating integer
- } else if (exp >= 0) {
- if (exp <= SINGLE_MAX_SMALL_TEN) {
- //
- // Can get the answer with one operation,
- // thus one roundoff.
- //
- fValue *= SINGLE_SMALL_10_POW[exp];
- return (isNegative) ? -fValue : fValue;
- }
- int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
- if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
- //
- // We can multiply fValue by 10^(slop)
- // and it is still "small" and exact.
- // Then we can multiply by 10^(exp-slop)
- // with one rounding.
- //
- fValue *= SINGLE_SMALL_10_POW[slop];
- fValue *= SINGLE_SMALL_10_POW[exp - slop];
- return (isNegative) ? -fValue : fValue;
- }
- //
- // Else we have a hard case with a positive exp.
- //
- } else {
- if (exp >= -SINGLE_MAX_SMALL_TEN) {
- //
- // Can get the answer in one division.
- //
- fValue /= SINGLE_SMALL_10_POW[-exp];
- return (isNegative) ? -fValue : fValue;
- }
- //
- // Else we have a hard case with a negative exp.
- //
- }
- } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
- //
- // In double-precision, this is an exact floating integer.
- // So we can compute to double, then shorten to float
- // with one round, and get the right answer.
- //
- // First, finish accumulating digits.
- // Then convert that integer to a double, multiply
- // by the appropriate power of ten, and convert to float.
- //
- long lValue = (long) iValue;
- for (int i = kDigits; i < nDigits; i++) {
- lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
- }
- double dValue = (double) lValue;
- exp = decExponent - nDigits;
- dValue *= SMALL_10_POW[exp];
- fValue = (float) dValue;
- return (isNegative) ? -fValue : fValue;
-
- }
- //
- // Harder cases:
- // The sum of digits plus exponent is greater than
- // what we think we can do with one error.
- //
- // Start by approximating the right answer by,
- // naively, scaling by powers of 10.
- // Scaling uses doubles to avoid overflow/underflow.
- //
- double dValue = fValue;
- if (exp > 0) {
- if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
- //
- // Lets face it. This is going to be
- // Infinity. Cut to the chase.
- //
- return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- }
- if ((exp & 15) != 0) {
- dValue *= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 0; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= BIG_10_POW[j];
- }
- }
- }
- } else if (exp < 0) {
- exp = -exp;
- if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
- //
- // Lets face it. This is going to be
- // zero. Cut to the chase.
- //
- return (isNegative) ? -0.0f : 0.0f;
- }
- if ((exp & 15) != 0) {
- dValue /= SMALL_10_POW[exp & 15];
- }
- if ((exp >>= 4) != 0) {
- int j;
- for (j = 0; exp > 0; j++, exp >>= 1) {
- if ((exp & 1) != 0) {
- dValue *= TINY_10_POW[j];
- }
- }
- }
- }
- fValue = Math.max(Float.MIN_VALUE, Math.min(Float.MAX_VALUE, (float) dValue));
-
- //
- // fValue is now approximately the result.
- // The hard part is adjusting it, by comparison
- // with FDBigInteger arithmetic.
- // Formulate the EXACT big-number result as
- // bigD0 * 10^exp
- //
- if (nDigits > SINGLE_MAX_NDIGITS) {
- nDigits = SINGLE_MAX_NDIGITS + 1;
- digits[SINGLE_MAX_NDIGITS] = '1';
- }
- FDBigInteger bigD0 = new FDBigInteger(iValue, digits, kDigits, nDigits);
- exp = decExponent - nDigits;
-
- int ieeeBits = Float.floatToRawIntBits(fValue); // IEEE-754 bits of float candidate
- final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
- final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
- bigD0 = bigD0.multByPow52(D5, 0);
- bigD0.makeImmutable(); // prevent bigD0 modification inside correctionLoop
- FDBigInteger bigD = null;
- int prevD2 = 0;
-
- correctionLoop:
- while (true) {
- // here ieeeBits can't be NaN, Infinity or zero
- int binexp = ieeeBits >>> SINGLE_EXP_SHIFT;
- int bigBbits = ieeeBits & FloatConsts.SIGNIF_BIT_MASK;
- if (binexp > 0) {
- bigBbits |= SINGLE_FRACT_HOB;
- } else { // Normalize denormalized numbers.
- assert bigBbits != 0 : bigBbits; // floatToBigInt(0.0)
- int leadingZeros = Integer.numberOfLeadingZeros(bigBbits);
- int shift = leadingZeros - (31 - SINGLE_EXP_SHIFT);
- bigBbits <<= shift;
- binexp = 1 - shift;
- }
- binexp -= FloatConsts.EXP_BIAS;
- int lowOrderZeros = Integer.numberOfTrailingZeros(bigBbits);
- bigBbits >>>= lowOrderZeros;
- final int bigIntExp = binexp - SINGLE_EXP_SHIFT + lowOrderZeros;
- final int bigIntNBits = SINGLE_EXP_SHIFT + 1 - lowOrderZeros;
-
- //
- // Scale bigD, bigB appropriately for
- // big-integer operations.
- // Naively, we multiply by powers of ten
- // and powers of two. What we actually do
- // is keep track of the powers of 5 and
- // powers of 2 we would use, then factor out
- // common divisors before doing the work.
- //
- int B2 = B5; // powers of 2 in bigB
- int D2 = D5; // powers of 2 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if (bigIntExp >= 0) {
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if (binexp <= -FloatConsts.EXP_BIAS) {
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(FloatConsts.EXP_BIAS+SINGLE_EXP_SHIFT+1)
- hulpbias = binexp + lowOrderZeros + FloatConsts.EXP_BIAS;
- } else {
- hulpbias = 1 + lowOrderZeros;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min(B2, Math.min(D2, Ulp2));
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
- if (bigD == null || prevD2 != D2) {
- bigD = bigD0.leftShift(D2);
- prevD2 = D2;
- }
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- FDBigInteger diff;
- int cmpResult;
- boolean overvalue;
- if ((cmpResult = bigB.cmp(bigD)) > 0) {
- overvalue = true; // our candidate is too big.
- diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
- if ((bigIntNBits == 1) && (bigIntExp > -FloatConsts.EXP_BIAS + 1)) {
- // candidate is a normalized exact power of 2 and
- // is too big (larger than Float.MIN_NORMAL). We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if (Ulp2 < 0) {
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff = diff.leftShift(1);
- }
- }
- } else if (cmpResult < 0) {
- overvalue = false; // our candidate is too small.
- diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- cmpResult = diff.cmpPow52(B5, Ulp2);
- if ((cmpResult) < 0) {
- // difference is small.
- // this is close enough
- break correctionLoop;
- } else if (cmpResult == 0) {
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- if ((ieeeBits & 1) != 0) { // half ties to even
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- ieeeBits += overvalue ? -1 : 1; // nextDown or nextUp
- if (ieeeBits == 0 || ieeeBits == FloatConsts.EXP_BIT_MASK) { // 0.0 or Float.POSITIVE_INFINITY
- break correctionLoop; // oops. Fell off end of range.
- }
- continue; // try again.
- }
-
- }
- if (isNegative) {
- ieeeBits |= FloatConsts.SIGN_BIT_MASK;
- }
- return Float.intBitsToFloat(ieeeBits);
- }
-
-
- /**
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
- */
- private static final double[] SMALL_10_POW = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float[] SINGLE_SMALL_10_POW = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double[] BIG_10_POW = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double[] TINY_10_POW = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
- private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
-
- }
-
- /**
- * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
- * The returned object is a <code>ThreadLocal</code> variable of this class.
- *
- * @param d The double precision value to convert.
- * @return The converter.
- */
- public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
- return getBinaryToASCIIConverter(d, true);
- }
-
- /**
- * Returns a <code>BinaryToASCIIConverter</code> for a <code>double</code>.
- * The returned object is a <code>ThreadLocal</code> variable of this class.
- *
- * @param d The double precision value to convert.
- * @param isCompatibleFormat
- * @return The converter.
- */
- static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
- long dBits = Double.doubleToRawLongBits(d);
- boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
- long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
- int binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
- // Discover obvious special cases of NaN and Infinity.
- if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
- if ( fractBits == 0L ){
- return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
- } else {
- return B2AC_NOT_A_NUMBER;
- }
- }
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- int nSignificantBits;
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
- }
- int leadingZeros = Long.numberOfLeadingZeros(fractBits);
- int shift = leadingZeros-(63-EXP_SHIFT);
- fractBits <<= shift;
- binExp = 1 - shift;
- nSignificantBits = 64-leadingZeros; // recall binExp is - shift count.
- } else {
- fractBits |= FRACT_HOB;
- nSignificantBits = EXP_SHIFT+1;
- }
- binExp -= DoubleConsts.EXP_BIAS;
- BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
- buf.setSign(isNegative);
- // call the routine that actually does all the hard work.
- buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
- return buf;
- }
-
- private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
- int fBits = Float.floatToRawIntBits( f );
- boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
- int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
- int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
- // Discover obvious special cases of NaN and Infinity.
- if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
- if ( fractBits == 0L ){
- return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
- } else {
- return B2AC_NOT_A_NUMBER;
- }
- }
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- int nSignificantBits;
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
- }
- int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
- int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
- fractBits <<= shift;
- binExp = 1 - shift;
- nSignificantBits = 32 - leadingZeros; // recall binExp is - shift count.
- } else {
- fractBits |= SINGLE_FRACT_HOB;
- nSignificantBits = SINGLE_EXP_SHIFT+1;
- }
- binExp -= FloatConsts.EXP_BIAS;
- BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
- buf.setSign(isNegative);
- // call the routine that actually does all the hard work.
- buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
- return buf;
- }
-
- @SuppressWarnings("fallthrough")
- static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
- boolean isNegative = false;
- boolean signSeen = false;
- int decExp;
- char c;
-
- parseNumber:
- try{
- in = in.trim(); // don't fool around with white space.
- // throws NullPointerException if null
- int len = in.length();
- if ( len == 0 ) {
- throw new NumberFormatException("empty String");
- }
- int i = 0;
- switch (in.charAt(i)){
- case '-':
- isNegative = true;
- //FALLTHROUGH
- case '+':
- i++;
- signSeen = true;
- }
- c = in.charAt(i);
- if(c == 'N') { // Check for NaN
- if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
- return A2BC_NOT_A_NUMBER;
- }
- // something went wrong, throw exception
- break parseNumber;
- } else if(c == 'I') { // Check for Infinity strings
- if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
- return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
- }
- // something went wrong, throw exception
- break parseNumber;
- } else if (c == '0') { // check for hexadecimal floating-point number
- if (len > i+1 ) {
- char ch = in.charAt(i+1);
- if (ch == 'x' || ch == 'X' ) { // possible hex string
- return parseHexString(in);
- }
- }
- } // look for and process decimal floating-point string
-
- char[] digits = new char[ len ];
- int nDigits= 0;
- boolean decSeen = false;
- int decPt = 0;
- int nLeadZero = 0;
- int nTrailZero= 0;
-
- skipLeadingZerosLoop:
- while (i < len) {
- c = in.charAt(i);
- if (c == '0') {
- nLeadZero++;
- } else if (c == '.') {
- if (decSeen) {
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if (signSeen) {
- decPt -= 1;
- }
- decSeen = true;
- } else {
- break skipLeadingZerosLoop;
- }
- i++;
- }
- digitLoop:
- while (i < len) {
- c = in.charAt(i);
- if (c >= '1' && c <= '9') {
- digits[nDigits++] = c;
- nTrailZero = 0;
- } else if (c == '0') {
- digits[nDigits++] = c;
- nTrailZero++;
- } else if (c == '.') {
- if (decSeen) {
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if (signSeen) {
- decPt -= 1;
- }
- decSeen = true;
- } else {
- break digitLoop;
- }
- i++;
- }
- nDigits -=nTrailZero;
- //
- // At this point, we've scanned all the digits and decimal
- // point we're going to see. Trim off leading and trailing
- // zeros, which will just confuse us later, and adjust
- // our initial decimal exponent accordingly.
- // To review:
- // we have seen i total characters.
- // nLeadZero of them were zeros before any other digits.
- // nTrailZero of them were zeros after any other digits.
- // if ( decSeen ), then a . was seen after decPt characters
- // ( including leading zeros which have been discarded )
- // nDigits characters were neither lead nor trailing
- // zeros, nor point
- //
- //
- // special hack: if we saw no non-zero digits, then the
- // answer is zero!
- // Unfortunately, we feel honor-bound to keep parsing!
- //
- boolean isZero = (nDigits == 0);
- if ( isZero && nLeadZero == 0 ){
- // we saw NO DIGITS AT ALL,
- // not even a crummy 0!
- // this is not allowed.
- break parseNumber; // go throw exception
- }
- //
- // Our initial exponent is decPt, adjusted by the number of
- // discarded zeros. Or, if there was no decPt,
- // then its just nDigits adjusted by discarded trailing zeros.
- //
- if ( decSeen ){
- decExp = decPt - nLeadZero;
- } else {
- decExp = nDigits + nTrailZero;
- }
-
- //
- // Look for 'e' or 'E' and an optionally signed integer.
- //
- if ( (i < len) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
- int expSign = 1;
- int expVal = 0;
- int reallyBig = Integer.MAX_VALUE / 10;
- boolean expOverflow = false;
- switch( in.charAt(++i) ){
- case '-':
- expSign = -1;
- //FALLTHROUGH
- case '+':
- i++;
- }
- int expAt = i;
- expLoop:
- while ( i < len ){
- if ( expVal >= reallyBig ){
- // the next character will cause integer
- // overflow.
- expOverflow = true;
- }
- c = in.charAt(i++);
- if(c>='0' && c<='9') {
- expVal = expVal*10 + ( (int)c - (int)'0' );
- } else {
- i--; // back up.
- break expLoop; // stop parsing exponent.
- }
- }
- int expLimit = BIG_DECIMAL_EXPONENT + nDigits + nTrailZero;
- if (expOverflow || (expVal > expLimit)) {
- // There is still a chance that the exponent will be safe to
- // use: if it would eventually decrease due to a negative
- // decExp, and that number is below the limit. We check for
- // that here.
- if (!expOverflow && (expSign == 1 && decExp < 0)
- && (expVal + decExp) < expLimit) {
- // Cannot overflow: adding a positive and negative number.
- decExp += expVal;
- } else {
- //
- // The intent here is to end up with
- // infinity or zero, as appropriate.
- // The reason for yielding such a small decExponent,
- // rather than something intuitive such as
- // expSign*Integer.MAX_VALUE, is that this value
- // is subject to further manipulation in
- // doubleValue() and floatValue(), and I don't want
- // it to be able to cause overflow there!
- // (The only way we can get into trouble here is for
- // really outrageous nDigits+nTrailZero, such as 2
- // billion.)
- //
- decExp = expSign * expLimit;
- }
- } else {
- // this should not overflow, since we tested
- // for expVal > (MAX+N), where N >= abs(decExp)
- decExp = decExp + expSign*expVal;
- }
-
- // if we saw something not a digit ( or end of string )
- // after the [Ee][+-], without seeing any digits at all
- // this is certainly an error. If we saw some digits,
- // but then some trailing garbage, that might be ok.
- // so we just fall through in that case.
- // HUMBUG
- if ( i == expAt ) {
- break parseNumber; // certainly bad
- }
- }
- //
- // We parsed everything we could.
- // If there are leftovers, then this is not good input!
- //
- if ( i < len &&
- ((i != len - 1) ||
- (in.charAt(i) != 'f' &&
- in.charAt(i) != 'F' &&
- in.charAt(i) != 'd' &&
- in.charAt(i) != 'D'))) {
- break parseNumber; // go throw exception
- }
- if(isZero) {
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- }
- return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
- } catch ( StringIndexOutOfBoundsException e ){ }
- throw new NumberFormatException("For input string: \"" + in + "\"");
- }
-
- private static class HexFloatPattern {
- /**
- * Grammar is compatible with hexadecimal floating-point constants
- * described in section 6.4.4.2 of the C99 specification.
- */
- private static final Pattern VALUE = Pattern.compile(
- //1 234 56 7 8 9
- "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
- );
- }
-
- /**
- * Converts string s to a suitable floating decimal; uses the
- * double constructor and sets the roundDir variable appropriately
- * in case the value is later converted to a float.
- *
- * @param s The <code>String</code> to parse.
- */
- static ASCIIToBinaryConverter parseHexString(String s) {
- // Verify string is a member of the hexadecimal floating-point
- // string language.
- Matcher m = HexFloatPattern.VALUE.matcher(s);
- boolean validInput = m.matches();
- if (!validInput) {
- // Input does not match pattern
- throw new NumberFormatException("For input string: \"" + s + "\"");
- } else { // validInput
- //
- // We must isolate the sign, significand, and exponent
- // fields. The sign value is straightforward. Since
- // floating-point numbers are stored with a normalized
- // representation, the significand and exponent are
- // interrelated.
- //
- // After extracting the sign, we normalized the
- // significand as a hexadecimal value, calculating an
- // exponent adjust for any shifts made during
- // normalization. If the significand is zero, the
- // exponent doesn't need to be examined since the output
- // will be zero.
- //
- // Next the exponent in the input string is extracted.
- // Afterwards, the significand is normalized as a *binary*
- // value and the input value's normalized exponent can be
- // computed. The significand bits are copied into a
- // double significand; if the string has more logical bits
- // than can fit in a double, the extra bits affect the
- // round and sticky bits which are used to round the final
- // value.
- //
- // Extract significand sign
- String group1 = m.group(1);
- boolean isNegative = ((group1 != null) && group1.equals("-"));
-
- // Extract Significand magnitude
- //
- // Based on the form of the significand, calculate how the
- // binary exponent needs to be adjusted to create a
- // normalized//hexadecimal* floating-point number; that
- // is, a number where there is one nonzero hex digit to
- // the left of the (hexa)decimal point. Since we are
- // adjusting a binary, not hexadecimal exponent, the
- // exponent is adjusted by a multiple of 4.
- //
- // There are a number of significand scenarios to consider;
- // letters are used in indicate nonzero digits:
- //
- // 1. 000xxxx => x.xxx normalized
- // increase exponent by (number of x's - 1)*4
- //
- // 2. 000xxx.yyyy => x.xxyyyy normalized
- // increase exponent by (number of x's - 1)*4
- //
- // 3. .000yyy => y.yy normalized
- // decrease exponent by (number of zeros + 1)*4
- //
- // 4. 000.00000yyy => y.yy normalized
- // decrease exponent by (number of zeros to right of point + 1)*4
- //
- // If the significand is exactly zero, return a properly
- // signed zero.
- //
-
- String significandString = null;
- int signifLength = 0;
- int exponentAdjust = 0;
- {
- int leftDigits = 0; // number of meaningful digits to
- // left of "decimal" point
- // (leading zeros stripped)
- int rightDigits = 0; // number of digits to right of
- // "decimal" point; leading zeros
- // must always be accounted for
- //
- // The significand is made up of either
- //
- // 1. group 4 entirely (integer portion only)
- //
- // OR
- //
- // 2. the fractional portion from group 7 plus any
- // (optional) integer portions from group 6.
- //
- String group4;
- if ((group4 = m.group(4)) != null) { // Integer-only significand
- // Leading zeros never matter on the integer portion
- significandString = stripLeadingZeros(group4);
- leftDigits = significandString.length();
- } else {
- // Group 6 is the optional integer; leading zeros
- // never matter on the integer portion
- String group6 = stripLeadingZeros(m.group(6));
- leftDigits = group6.length();
-
- // fraction
- String group7 = m.group(7);
- rightDigits = group7.length();
-
- // Turn "integer.fraction" into "integer"+"fraction"
- significandString =
- ((group6 == null) ? "" : group6) + // is the null
- // check necessary?
- group7;
- }
-
- significandString = stripLeadingZeros(significandString);
- signifLength = significandString.length();
-
- //
- // Adjust exponent as described above
- //
- if (leftDigits >= 1) { // Cases 1 and 2
- exponentAdjust = 4 * (leftDigits - 1);
- } else { // Cases 3 and 4
- exponentAdjust = -4 * (rightDigits - signifLength + 1);
- }
-
- // If the significand is zero, the exponent doesn't
- // matter; return a properly signed zero.
-
- if (signifLength == 0) { // Only zeros in input
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- }
- }
-
- // Extract Exponent
- //
- // Use an int to read in the exponent value; this should
- // provide more than sufficient range for non-contrived
- // inputs. If reading the exponent in as an int does
- // overflow, examine the sign of the exponent and
- // significand to determine what to do.
- //
- String group8 = m.group(8);
- boolean positiveExponent = (group8 == null) || group8.equals("+");
- long unsignedRawExponent;
- try {
- unsignedRawExponent = Integer.parseInt(m.group(9));
- }
- catch (NumberFormatException e) {
- // At this point, we know the exponent is
- // syntactically well-formed as a sequence of
- // digits. Therefore, if an NumberFormatException
- // is thrown, it must be due to overflowing int's
- // range. Also, at this point, we have already
- // checked for a zero significand. Thus the signs
- // of the exponent and significand determine the
- // final result:
- //
- // significand
- // + -
- // exponent + +infinity -infinity
- // - +0.0 -0.0
- return isNegative ?
- (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
- : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
-
- }
-
- long rawExponent =
- (positiveExponent ? 1L : -1L) * // exponent sign
- unsignedRawExponent; // exponent magnitude
-
- // Calculate partially adjusted exponent
- long exponent = rawExponent + exponentAdjust;
-
- // Starting copying non-zero bits into proper position in
- // a long; copy explicit bit too; this will be masked
- // later for normal values.
-
- boolean round = false;
- boolean sticky = false;
- int nextShift = 0;
- long significand = 0L;
- // First iteration is different, since we only copy
- // from the leading significand bit; one more exponent
- // adjust will be needed...
-
- // IMPORTANT: make leadingDigit a long to avoid
- // surprising shift semantics!
- long leadingDigit = getHexDigit(significandString, 0);
-
- //
- // Left shift the leading digit (53 - (bit position of
- // leading 1 in digit)); this sets the top bit of the
- // significand to 1. The nextShift value is adjusted
- // to take into account the number of bit positions of
- // the leadingDigit actually used. Finally, the
- // exponent is adjusted to normalize the significand
- // as a binary value, not just a hex value.
- //
- if (leadingDigit == 1) {
- significand |= leadingDigit << 52;
- nextShift = 52 - 4;
- // exponent += 0
- } else if (leadingDigit <= 3) { // [2, 3]
- significand |= leadingDigit << 51;
- nextShift = 52 - 5;
- exponent += 1;
- } else if (leadingDigit <= 7) { // [4, 7]
- significand |= leadingDigit << 50;
- nextShift = 52 - 6;
- exponent += 2;
- } else if (leadingDigit <= 15) { // [8, f]
- significand |= leadingDigit << 49;
- nextShift = 52 - 7;
- exponent += 3;
- } else {
- throw new AssertionError("Result from digit conversion too large!");
- }
- // The preceding if-else could be replaced by a single
- // code block based on the high-order bit set in
- // leadingDigit. Given leadingOnePosition,
-
- // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
- // nextShift = 52 - (3 + leadingOnePosition);
- // exponent += (leadingOnePosition-1);
-
- //
- // Now the exponent variable is equal to the normalized
- // binary exponent. Code below will make representation
- // adjustments if the exponent is incremented after
- // rounding (includes overflows to infinity) or if the
- // result is subnormal.
- //
-
- // Copy digit into significand until the significand can't
- // hold another full hex digit or there are no more input
- // hex digits.
- int i = 0;
- for (i = 1;
- i < signifLength && nextShift >= 0;
- i++) {
- long currentDigit = getHexDigit(significandString, i);
- significand |= (currentDigit << nextShift);
- nextShift -= 4;
- }
-
- // After the above loop, the bulk of the string is copied.
- // Now, we must copy any partial hex digits into the
- // significand AND compute the round bit and start computing
- // sticky bit.
-
- if (i < signifLength) { // at least one hex input digit exists
- long currentDigit = getHexDigit(significandString, i);
-
- // from nextShift, figure out how many bits need
- // to be copied, if any
- switch (nextShift) { // must be negative
- case -1:
- // three bits need to be copied in; can
- // set round bit
- significand |= ((currentDigit & 0xEL) >> 1);
- round = (currentDigit & 0x1L) != 0L;
- break;
-
- case -2:
- // two bits need to be copied in; can
- // set round and start sticky
- significand |= ((currentDigit & 0xCL) >> 2);
- round = (currentDigit & 0x2L) != 0L;
- sticky = (currentDigit & 0x1L) != 0;
- break;
-
- case -3:
- // one bit needs to be copied in
- significand |= ((currentDigit & 0x8L) >> 3);
- // Now set round and start sticky, if possible
- round = (currentDigit & 0x4L) != 0L;
- sticky = (currentDigit & 0x3L) != 0;
- break;
-
- case -4:
- // all bits copied into significand; set
- // round and start sticky
- round = ((currentDigit & 0x8L) != 0); // is top bit set?
- // nonzeros in three low order bits?
- sticky = (currentDigit & 0x7L) != 0;
- break;
-
- default:
- throw new AssertionError("Unexpected shift distance remainder.");
- // break;
- }
-
- // Round is set; sticky might be set.
-
- // For the sticky bit, it suffices to check the
- // current digit and test for any nonzero digits in
- // the remaining unprocessed input.
- i++;
- while (i < signifLength && !sticky) {
- currentDigit = getHexDigit(significandString, i);
- sticky = sticky || (currentDigit != 0);
- i++;
- }
-
- }
- // else all of string was seen, round and sticky are
- // correct as false.
-
- // Float calculations
- int floatBits = isNegative ? FloatConsts.SIGN_BIT_MASK : 0;
- if (exponent >= FloatConsts.MIN_EXPONENT) {
- if (exponent > FloatConsts.MAX_EXPONENT) {
- // Float.POSITIVE_INFINITY
- floatBits |= FloatConsts.EXP_BIT_MASK;
- } else {
- int threshShift = DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH - 1;
- boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
- int iValue = (int) (significand >>> threshShift);
- if ((iValue & 3) != 1 || floatSticky) {
- iValue++;
- }
- floatBits |= (((((int) exponent) + (FloatConsts.EXP_BIAS - 1))) << SINGLE_EXP_SHIFT) + (iValue >> 1);
- }
- } else {
- if (exponent < FloatConsts.MIN_SUB_EXPONENT - 1) {
- // 0
- } else {
- // exponent == -127 ==> threshShift = 53 - 2 + (-149) - (-127) = 53 - 24
- int threshShift = (int) ((DoubleConsts.SIGNIFICAND_WIDTH - 2 + FloatConsts.MIN_SUB_EXPONENT) - exponent);
- assert threshShift >= DoubleConsts.SIGNIFICAND_WIDTH - FloatConsts.SIGNIFICAND_WIDTH;
- assert threshShift < DoubleConsts.SIGNIFICAND_WIDTH;
- boolean floatSticky = (significand & ((1L << threshShift) - 1)) != 0 || round || sticky;
- int iValue = (int) (significand >>> threshShift);
- if ((iValue & 3) != 1 || floatSticky) {
- iValue++;
- }
- floatBits |= iValue >> 1;
- }
- }
- float fValue = Float.intBitsToFloat(floatBits);
-
- // Check for overflow and update exponent accordingly.
- if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result
- // overflow to properly signed infinity
- return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
- } else { // Finite return value
- if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
- exponent >= DoubleConsts.MIN_EXPONENT) {
-
- // The result returned in this block cannot be a
- // zero or subnormal; however after the
- // significand is adjusted from rounding, we could
- // still overflow in infinity.
-
- // AND exponent bits into significand; if the
- // significand is incremented and overflows from
- // rounding, this combination will update the
- // exponent correctly, even in the case of
- // Double.MAX_VALUE overflowing to infinity.
-
- significand = ((( exponent +
- (long) DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH - 1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
- } else { // Subnormal or zero
- // (exponent < DoubleConsts.MIN_EXPONENT)
-
- if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
- // No way to round back to nonzero value
- // regardless of significand if the exponent is
- // less than -1075.
- return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
- } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
- //
- // Find bit position to round to; recompute
- // round and sticky bits, and shift
- // significand right appropriately.
- //
-
- sticky = sticky || round;
- round = false;
-
- // Number of bits of significand to preserve is
- // exponent - abs_min_exp +1
- // check:
- // -1075 +1074 + 1 = 0
- // -1023 +1074 + 1 = 52
-
- int bitsDiscarded = 53 -
- ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
- assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
- // What to do here:
- // First, isolate the new round bit
- round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
- if (bitsDiscarded > 1) {
- // create mask to update sticky bits; low
- // order bitsDiscarded bits should be 1
- long mask = ~((~0L) << (bitsDiscarded - 1));
- sticky = sticky || ((significand & mask) != 0L);
- }
-
- // Now, discard the bits
- significand = significand >> bitsDiscarded;
-
- significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
- (long) DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH - 1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
- }
- }
-
- // The significand variable now contains the currently
- // appropriate exponent bits too.
-
- //
- // Determine if significand should be incremented;
- // making this determination depends on the least
- // significant bit and the round and sticky bits.
- //
- // Round to nearest even rounding table, adapted from
- // table 4.7 in "Computer Arithmetic" by IsraelKoren.
- // The digit to the left of the "decimal" point is the
- // least significant bit, the digits to the right of
- // the point are the round and sticky bits
- //
- // Number Round(x)
- // x0.00 x0.
- // x0.01 x0.
- // x0.10 x0.
- // x0.11 x1. = x0. +1
- // x1.00 x1.
- // x1.01 x1.
- // x1.10 x1. + 1
- // x1.11 x1. + 1
- //
- boolean leastZero = ((significand & 1L) == 0L);
- if ((leastZero && round && sticky) ||
- ((!leastZero) && round)) {
- significand++;
- }
-
- double value = isNegative ?
- Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
- Double.longBitsToDouble(significand );
-
- return new PreparedASCIIToBinaryBuffer(value, fValue);
- }
- }
- }
-
- /**
- * Returns <code>s</code> with any leading zeros removed.
- */
- static String stripLeadingZeros(String s) {
-// return s.replaceFirst("^0+", "");
- if(!s.isEmpty() && s.charAt(0)=='0') {
- for(int i=1; i<s.length(); i++) {
- if(s.charAt(i)!='0') {
- return s.substring(i);
- }
- }
- return "";
- }
- return s;
- }
-
- /**
- * Extracts a hexadecimal digit from position <code>position</code>
- * of string <code>s</code>.
- */
- static int getHexDigit(String s, int position) {
- int value = Character.digit(s.charAt(position), 16);
- if (value <= -1 || value >= 16) {
- throw new AssertionError("Unexpected failure of digit conversion of " +
- s.charAt(position));
- }
- return value;
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/FormattedFloatingDecimal.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.misc;
-
-import java.util.Arrays;
-
-public class FormattedFloatingDecimal{
-
- public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
-
-
- public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
- FloatingDecimal.BinaryToASCIIConverter fdConverter =
- FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
- return new FormattedFloatingDecimal(precision,form, fdConverter);
- }
-
- private int decExponentRounded;
- private char[] mantissa;
- private char[] exponent;
-
- private static final ThreadLocal<Object> threadLocalCharBuffer =
- new ThreadLocal<Object>() {
- @Override
- protected Object initialValue() {
- return new char[20];
- }
- };
-
- private static char[] getBuffer(){
- return (char[]) threadLocalCharBuffer.get();
- }
-
- private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
- if (fdConverter.isExceptional()) {
- this.mantissa = fdConverter.toJavaFormatString().toCharArray();
- this.exponent = null;
- return;
- }
- char[] digits = getBuffer();
- int nDigits = fdConverter.getDigits(digits);
- int decExp = fdConverter.getDecimalExponent();
- int exp;
- boolean isNegative = fdConverter.isNegative();
- switch (form) {
- case COMPATIBLE:
- exp = decExp;
- this.decExponentRounded = exp;
- fillCompatible(precision, digits, nDigits, exp, isNegative);
- break;
- case DECIMAL_FLOAT:
- exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
- fillDecimal(precision, digits, nDigits, exp, isNegative);
- this.decExponentRounded = exp;
- break;
- case SCIENTIFIC:
- exp = applyPrecision(decExp, digits, nDigits, precision + 1);
- fillScientific(precision, digits, nDigits, exp, isNegative);
- this.decExponentRounded = exp;
- break;
- case GENERAL:
- exp = applyPrecision(decExp, digits, nDigits, precision);
- // adjust precision to be the number of digits to right of decimal
- // the real exponent to be output is actually exp - 1, not exp
- if (exp - 1 < -4 || exp - 1 >= precision) {
- // form = Form.SCIENTIFIC;
- precision--;
- fillScientific(precision, digits, nDigits, exp, isNegative);
- } else {
- // form = Form.DECIMAL_FLOAT;
- precision = precision - exp;
- fillDecimal(precision, digits, nDigits, exp, isNegative);
- }
- this.decExponentRounded = exp;
- break;
- default:
- assert false;
- }
- }
-
- // returns the exponent after rounding has been done by applyPrecision
- public int getExponentRounded() {
- return decExponentRounded - 1;
- }
-
- public char[] getMantissa(){
- return mantissa;
- }
-
- public char[] getExponent(){
- return exponent;
- }
-
- /**
- * Returns new decExp in case of overflow.
- */
- private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
- if (prec >= nDigits || prec < 0) {
- // no rounding necessary
- return decExp;
- }
- if (prec == 0) {
- // only one digit (0 or 1) is returned because the precision
- // excludes all significant digits
- if (digits[0] >= '5') {
- digits[0] = '1';
- Arrays.fill(digits, 1, nDigits, '0');
- return decExp + 1;
- } else {
- Arrays.fill(digits, 0, nDigits, '0');
- return decExp;
- }
- }
- int q = digits[prec];
- if (q >= '5') {
- int i = prec;
- q = digits[--i];
- if ( q == '9' ) {
- while ( q == '9' && i > 0 ){
- q = digits[--i];
- }
- if ( q == '9' ){
- // carryout! High-order 1, rest 0s, larger exp.
- digits[0] = '1';
- Arrays.fill(digits, 1, nDigits, '0');
- return decExp+1;
- }
- }
- digits[i] = (char)(q + 1);
- Arrays.fill(digits, i+1, nDigits, '0');
- } else {
- Arrays.fill(digits, prec, nDigits, '0');
- }
- return decExp;
- }
-
- /**
- * Fills mantissa and exponent char arrays for compatible format.
- */
- private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
- int startIndex = isNegative ? 1 : 0;
- if (exp > 0 && exp < 8) {
- // print digits.digits.
- if (nDigits < exp) {
- int extraZeros = exp - nDigits;
- mantissa = create(isNegative, nDigits + extraZeros + 2);
- System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
- Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
- mantissa[startIndex + nDigits + extraZeros] = '.';
- mantissa[startIndex + nDigits + extraZeros+1] = '0';
- } else if (exp < nDigits) {
- int t = Math.min(nDigits - exp, precision);
- mantissa = create(isNegative, exp + 1 + t);
- System.arraycopy(digits, 0, mantissa, startIndex, exp);
- mantissa[startIndex + exp ] = '.';
- System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
- } else { // exp == digits.length
- mantissa = create(isNegative, nDigits + 2);
- System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
- mantissa[startIndex + nDigits ] = '.';
- mantissa[startIndex + nDigits +1] = '0';
- }
- } else if (exp <= 0 && exp > -3) {
- int zeros = Math.max(0, Math.min(-exp, precision));
- int t = Math.max(0, Math.min(nDigits, precision + exp));
- // write '0' s before the significant digits
- if (zeros > 0) {
- mantissa = create(isNegative, zeros + 2 + t);
- mantissa[startIndex] = '0';
- mantissa[startIndex+1] = '.';
- Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
- if (t > 0) {
- // copy only when significant digits are within the precision
- System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
- }
- } else if (t > 0) {
- mantissa = create(isNegative, zeros + 2 + t);
- mantissa[startIndex] = '0';
- mantissa[startIndex + 1] = '.';
- // copy only when significant digits are within the precision
- System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
- } else {
- this.mantissa = create(isNegative, 1);
- this.mantissa[startIndex] = '0';
- }
- } else {
- if (nDigits > 1) {
- mantissa = create(isNegative, nDigits + 1);
- mantissa[startIndex] = digits[0];
- mantissa[startIndex + 1] = '.';
- System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
- } else {
- mantissa = create(isNegative, 3);
- mantissa[startIndex] = digits[0];
- mantissa[startIndex + 1] = '.';
- mantissa[startIndex + 2] = '0';
- }
- int e, expStartIntex;
- boolean isNegExp = (exp <= 0);
- if (isNegExp) {
- e = -exp + 1;
- expStartIntex = 1;
- } else {
- e = exp - 1;
- expStartIntex = 0;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- exponent = create(isNegExp,1);
- exponent[expStartIntex] = (char) (e + '0');
- } else if (e <= 99) {
- exponent = create(isNegExp,2);
- exponent[expStartIntex] = (char) (e / 10 + '0');
- exponent[expStartIntex+1] = (char) (e % 10 + '0');
- } else {
- exponent = create(isNegExp,3);
- exponent[expStartIntex] = (char) (e / 100 + '0');
- e %= 100;
- exponent[expStartIntex+1] = (char) (e / 10 + '0');
- exponent[expStartIntex+2] = (char) (e % 10 + '0');
- }
- }
- }
-
- private static char[] create(boolean isNegative, int size) {
- if(isNegative) {
- char[] r = new char[size +1];
- r[0] = '-';
- return r;
- } else {
- return new char[size];
- }
- }
-
- /*
- * Fills mantissa char arrays for DECIMAL_FLOAT format.
- * Exponent should be equal to null.
- */
- private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
- int startIndex = isNegative ? 1 : 0;
- if (exp > 0) {
- // print digits.digits.
- if (nDigits < exp) {
- mantissa = create(isNegative,exp);
- System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
- Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
- // Do not append ".0" for formatted floats since the user
- // may request that it be omitted. It is added as necessary
- // by the Formatter.
- } else {
- int t = Math.min(nDigits - exp, precision);
- mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
- System.arraycopy(digits, 0, mantissa, startIndex, exp);
- // Do not append ".0" for formatted floats since the user
- // may request that it be omitted. It is added as necessary
- // by the Formatter.
- if (t > 0) {
- mantissa[startIndex + exp] = '.';
- System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
- }
- }
- } else if (exp <= 0) {
- int zeros = Math.max(0, Math.min(-exp, precision));
- int t = Math.max(0, Math.min(nDigits, precision + exp));
- // write '0' s before the significant digits
- if (zeros > 0) {
- mantissa = create(isNegative, zeros + 2 + t);
- mantissa[startIndex] = '0';
- mantissa[startIndex+1] = '.';
- Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
- if (t > 0) {
- // copy only when significant digits are within the precision
- System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
- }
- } else if (t > 0) {
- mantissa = create(isNegative, zeros + 2 + t);
- mantissa[startIndex] = '0';
- mantissa[startIndex + 1] = '.';
- // copy only when significant digits are within the precision
- System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
- } else {
- this.mantissa = create(isNegative, 1);
- this.mantissa[startIndex] = '0';
- }
- }
- }
-
- /**
- * Fills mantissa and exponent char arrays for SCIENTIFIC format.
- */
- private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
- int startIndex = isNegative ? 1 : 0;
- int t = Math.max(0, Math.min(nDigits - 1, precision));
- if (t > 0) {
- mantissa = create(isNegative, t + 2);
- mantissa[startIndex] = digits[0];
- mantissa[startIndex + 1] = '.';
- System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
- } else {
- mantissa = create(isNegative, 1);
- mantissa[startIndex] = digits[0];
- }
- char expSign;
- int e;
- if (exp <= 0) {
- expSign = '-';
- e = -exp + 1;
- } else {
- expSign = '+' ;
- e = exp - 1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- exponent = new char[] { expSign,
- '0', (char) (e + '0') };
- } else if (e <= 99) {
- exponent = new char[] { expSign,
- (char) (e / 10 + '0'), (char) (e % 10 + '0') };
- } else {
- char hiExpChar = (char) (e / 100 + '0');
- e %= 100;
- exponent = new char[] { expSign,
- hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
- }
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/GC.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/misc/GC.java Wed Jan 06 14:54:24 2016 +0000
@@ -82,7 +82,7 @@
*/
public static native long maxObjectInspectionAge();
- private static class Daemon extends ManagedLocalsThread {
+ private static class Daemon extends Thread {
public void run() {
for (;;) {
@@ -122,7 +122,7 @@
}
private Daemon(ThreadGroup tg) {
- super(tg, "GC Daemon");
+ super(tg, null, "GC Daemon", 0L, false);
}
/* Create a new daemon thread in the root thread group */
--- a/jdk/src/java.base/share/classes/sun/misc/HexDumpEncoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, 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.misc;
-import java.io.PrintStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-/**
- * This class encodes a buffer into the classic: "Hexadecimal Dump" format of
- * the past. It is useful for analyzing the contents of binary buffers.
- * The format produced is as follows:
- * <pre>
- * xxxx: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ................
- * </pre>
- * Where xxxx is the offset into the buffer in 16 byte chunks, followed
- * by ascii coded hexadecimal bytes followed by the ASCII representation of
- * the bytes or '.' if they are not valid bytes.
- *
- * @author Chuck McManis
- */
-
-public class HexDumpEncoder extends CharacterEncoder {
-
- private int offset;
- private int thisLineLength;
- private int currentByte;
- private byte thisLine[] = new byte[16];
-
- static void hexDigit(PrintStream p, byte x) {
- char c;
-
- c = (char) ((x >> 4) & 0xf);
- if (c > 9)
- c = (char) ((c-10) + 'A');
- else
- c = (char)(c + '0');
- p.write(c);
- c = (char) (x & 0xf);
- if (c > 9)
- c = (char)((c-10) + 'A');
- else
- c = (char)(c + '0');
- p.write(c);
- }
-
- protected int bytesPerAtom() {
- return (1);
- }
-
- protected int bytesPerLine() {
- return (16);
- }
-
- protected void encodeBufferPrefix(OutputStream o) throws IOException {
- offset = 0;
- super.encodeBufferPrefix(o);
- }
-
- protected void encodeLinePrefix(OutputStream o, int len) throws IOException {
- hexDigit(pStream, (byte)((offset >>> 8) & 0xff));
- hexDigit(pStream, (byte)(offset & 0xff));
- pStream.print(": ");
- currentByte = 0;
- thisLineLength = len;
- }
-
- protected void encodeAtom(OutputStream o, byte buf[], int off, int len) throws IOException {
- thisLine[currentByte] = buf[off];
- hexDigit(pStream, buf[off]);
- pStream.print(" ");
- currentByte++;
- if (currentByte == 8)
- pStream.print(" ");
- }
-
- protected void encodeLineSuffix(OutputStream o) throws IOException {
- if (thisLineLength < 16) {
- for (int i = thisLineLength; i < 16; i++) {
- pStream.print(" ");
- if (i == 7)
- pStream.print(" ");
- }
- }
- pStream.print(" ");
- for (int i = 0; i < thisLineLength; i++) {
- if ((thisLine[i] < ' ') || (thisLine[i] > 'z')) {
- pStream.print(".");
- } else {
- pStream.write(thisLine[i]);
- }
- }
- pStream.println();
- offset += thisLineLength;
- }
-
-}
--- a/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/misc/InnocuousThread.java Wed Jan 06 14:54:24 2016 +0000
@@ -35,8 +35,10 @@
* A thread that has no permissions, is not a member of any user-defined
* ThreadGroup and supports the ability to erase ThreadLocals.
*/
-public final class InnocuousThread extends ManagedLocalsThread {
+public final class InnocuousThread extends Thread {
private static final jdk.internal.misc.Unsafe UNSAFE;
+ private static final long THREAD_LOCALS;
+ private static final long INHERITABLE_THREAD_LOCALS;
private static final ThreadGroup INNOCUOUSTHREADGROUP;
private static final AccessControlContext ACC;
private static final long INHERITEDACCESSCONTROLCONTEXT;
@@ -54,7 +56,7 @@
}
public InnocuousThread(ThreadGroup group, Runnable target, String name) {
- super(group, target, name);
+ super(group, target, name, 0L, false);
UNSAFE.putOrderedObject(this, INHERITEDACCESSCONTROLCONTEXT, ACC);
UNSAFE.putOrderedObject(this, CONTEXTCLASSLOADER, ClassLoader.getSystemClassLoader());
}
@@ -73,6 +75,14 @@
throw new SecurityException("setContextClassLoader");
}
+ /**
+ * Drops all thread locals (and inherited thread locals).
+ */
+ public final void eraseThreadLocals() {
+ UNSAFE.putObject(this, THREAD_LOCALS, null);
+ UNSAFE.putObject(this, INHERITABLE_THREAD_LOCALS, null);
+ }
+
// ensure run method is run only once
private volatile boolean hasRun;
@@ -96,6 +106,10 @@
Class<?> tk = Thread.class;
Class<?> gk = ThreadGroup.class;
+ THREAD_LOCALS = UNSAFE.objectFieldOffset
+ (tk.getDeclaredField("threadLocals"));
+ INHERITABLE_THREAD_LOCALS = UNSAFE.objectFieldOffset
+ (tk.getDeclaredField("inheritableThreadLocals"));
INHERITEDACCESSCONTROLCONTEXT = UNSAFE.objectFieldOffset
(tk.getDeclaredField("inheritedAccessControlContext"));
CONTEXTCLASSLOADER = UNSAFE.objectFieldOffset
--- a/jdk/src/java.base/share/classes/sun/misc/ProxyGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2031 +0,0 @@
-/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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.misc;
-
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Array;
-import java.lang.reflect.Method;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import sun.security.action.GetBooleanAction;
-
-/**
- * ProxyGenerator contains the code to generate a dynamic proxy class
- * for the java.lang.reflect.Proxy API.
- *
- * The external interfaces to ProxyGenerator is the static
- * "generateProxyClass" method.
- *
- * @author Peter Jones
- * @since 1.3
- */
-public class ProxyGenerator {
- /*
- * In the comments below, "JVMS" refers to The Java Virtual Machine
- * Specification Second Edition and "JLS" refers to the original
- * version of The Java Language Specification, unless otherwise
- * specified.
- */
-
- /* generate 1.5-era class file version */
- private static final int CLASSFILE_MAJOR_VERSION = 49;
- private static final int CLASSFILE_MINOR_VERSION = 0;
-
- /*
- * beginning of constants copied from
- * sun.tools.java.RuntimeConstants (which no longer exists):
- */
-
- /* constant pool tags */
- private static final int CONSTANT_UTF8 = 1;
- private static final int CONSTANT_UNICODE = 2;
- private static final int CONSTANT_INTEGER = 3;
- private static final int CONSTANT_FLOAT = 4;
- private static final int CONSTANT_LONG = 5;
- private static final int CONSTANT_DOUBLE = 6;
- private static final int CONSTANT_CLASS = 7;
- private static final int CONSTANT_STRING = 8;
- private static final int CONSTANT_FIELD = 9;
- private static final int CONSTANT_METHOD = 10;
- private static final int CONSTANT_INTERFACEMETHOD = 11;
- private static final int CONSTANT_NAMEANDTYPE = 12;
-
- /* access and modifier flags */
- private static final int ACC_PUBLIC = 0x00000001;
- private static final int ACC_PRIVATE = 0x00000002;
-// private static final int ACC_PROTECTED = 0x00000004;
- private static final int ACC_STATIC = 0x00000008;
- private static final int ACC_FINAL = 0x00000010;
-// private static final int ACC_SYNCHRONIZED = 0x00000020;
-// private static final int ACC_VOLATILE = 0x00000040;
-// private static final int ACC_TRANSIENT = 0x00000080;
-// private static final int ACC_NATIVE = 0x00000100;
-// private static final int ACC_INTERFACE = 0x00000200;
-// private static final int ACC_ABSTRACT = 0x00000400;
- private static final int ACC_SUPER = 0x00000020;
-// private static final int ACC_STRICT = 0x00000800;
-
- /* opcodes */
-// private static final int opc_nop = 0;
- private static final int opc_aconst_null = 1;
-// private static final int opc_iconst_m1 = 2;
- private static final int opc_iconst_0 = 3;
-// private static final int opc_iconst_1 = 4;
-// private static final int opc_iconst_2 = 5;
-// private static final int opc_iconst_3 = 6;
-// private static final int opc_iconst_4 = 7;
-// private static final int opc_iconst_5 = 8;
-// private static final int opc_lconst_0 = 9;
-// private static final int opc_lconst_1 = 10;
-// private static final int opc_fconst_0 = 11;
-// private static final int opc_fconst_1 = 12;
-// private static final int opc_fconst_2 = 13;
-// private static final int opc_dconst_0 = 14;
-// private static final int opc_dconst_1 = 15;
- private static final int opc_bipush = 16;
- private static final int opc_sipush = 17;
- private static final int opc_ldc = 18;
- private static final int opc_ldc_w = 19;
-// private static final int opc_ldc2_w = 20;
- private static final int opc_iload = 21;
- private static final int opc_lload = 22;
- private static final int opc_fload = 23;
- private static final int opc_dload = 24;
- private static final int opc_aload = 25;
- private static final int opc_iload_0 = 26;
-// private static final int opc_iload_1 = 27;
-// private static final int opc_iload_2 = 28;
-// private static final int opc_iload_3 = 29;
- private static final int opc_lload_0 = 30;
-// private static final int opc_lload_1 = 31;
-// private static final int opc_lload_2 = 32;
-// private static final int opc_lload_3 = 33;
- private static final int opc_fload_0 = 34;
-// private static final int opc_fload_1 = 35;
-// private static final int opc_fload_2 = 36;
-// private static final int opc_fload_3 = 37;
- private static final int opc_dload_0 = 38;
-// private static final int opc_dload_1 = 39;
-// private static final int opc_dload_2 = 40;
-// private static final int opc_dload_3 = 41;
- private static final int opc_aload_0 = 42;
-// private static final int opc_aload_1 = 43;
-// private static final int opc_aload_2 = 44;
-// private static final int opc_aload_3 = 45;
-// private static final int opc_iaload = 46;
-// private static final int opc_laload = 47;
-// private static final int opc_faload = 48;
-// private static final int opc_daload = 49;
-// private static final int opc_aaload = 50;
-// private static final int opc_baload = 51;
-// private static final int opc_caload = 52;
-// private static final int opc_saload = 53;
-// private static final int opc_istore = 54;
-// private static final int opc_lstore = 55;
-// private static final int opc_fstore = 56;
-// private static final int opc_dstore = 57;
- private static final int opc_astore = 58;
-// private static final int opc_istore_0 = 59;
-// private static final int opc_istore_1 = 60;
-// private static final int opc_istore_2 = 61;
-// private static final int opc_istore_3 = 62;
-// private static final int opc_lstore_0 = 63;
-// private static final int opc_lstore_1 = 64;
-// private static final int opc_lstore_2 = 65;
-// private static final int opc_lstore_3 = 66;
-// private static final int opc_fstore_0 = 67;
-// private static final int opc_fstore_1 = 68;
-// private static final int opc_fstore_2 = 69;
-// private static final int opc_fstore_3 = 70;
-// private static final int opc_dstore_0 = 71;
-// private static final int opc_dstore_1 = 72;
-// private static final int opc_dstore_2 = 73;
-// private static final int opc_dstore_3 = 74;
- private static final int opc_astore_0 = 75;
-// private static final int opc_astore_1 = 76;
-// private static final int opc_astore_2 = 77;
-// private static final int opc_astore_3 = 78;
-// private static final int opc_iastore = 79;
-// private static final int opc_lastore = 80;
-// private static final int opc_fastore = 81;
-// private static final int opc_dastore = 82;
- private static final int opc_aastore = 83;
-// private static final int opc_bastore = 84;
-// private static final int opc_castore = 85;
-// private static final int opc_sastore = 86;
- private static final int opc_pop = 87;
-// private static final int opc_pop2 = 88;
- private static final int opc_dup = 89;
-// private static final int opc_dup_x1 = 90;
-// private static final int opc_dup_x2 = 91;
-// private static final int opc_dup2 = 92;
-// private static final int opc_dup2_x1 = 93;
-// private static final int opc_dup2_x2 = 94;
-// private static final int opc_swap = 95;
-// private static final int opc_iadd = 96;
-// private static final int opc_ladd = 97;
-// private static final int opc_fadd = 98;
-// private static final int opc_dadd = 99;
-// private static final int opc_isub = 100;
-// private static final int opc_lsub = 101;
-// private static final int opc_fsub = 102;
-// private static final int opc_dsub = 103;
-// private static final int opc_imul = 104;
-// private static final int opc_lmul = 105;
-// private static final int opc_fmul = 106;
-// private static final int opc_dmul = 107;
-// private static final int opc_idiv = 108;
-// private static final int opc_ldiv = 109;
-// private static final int opc_fdiv = 110;
-// private static final int opc_ddiv = 111;
-// private static final int opc_irem = 112;
-// private static final int opc_lrem = 113;
-// private static final int opc_frem = 114;
-// private static final int opc_drem = 115;
-// private static final int opc_ineg = 116;
-// private static final int opc_lneg = 117;
-// private static final int opc_fneg = 118;
-// private static final int opc_dneg = 119;
-// private static final int opc_ishl = 120;
-// private static final int opc_lshl = 121;
-// private static final int opc_ishr = 122;
-// private static final int opc_lshr = 123;
-// private static final int opc_iushr = 124;
-// private static final int opc_lushr = 125;
-// private static final int opc_iand = 126;
-// private static final int opc_land = 127;
-// private static final int opc_ior = 128;
-// private static final int opc_lor = 129;
-// private static final int opc_ixor = 130;
-// private static final int opc_lxor = 131;
-// private static final int opc_iinc = 132;
-// private static final int opc_i2l = 133;
-// private static final int opc_i2f = 134;
-// private static final int opc_i2d = 135;
-// private static final int opc_l2i = 136;
-// private static final int opc_l2f = 137;
-// private static final int opc_l2d = 138;
-// private static final int opc_f2i = 139;
-// private static final int opc_f2l = 140;
-// private static final int opc_f2d = 141;
-// private static final int opc_d2i = 142;
-// private static final int opc_d2l = 143;
-// private static final int opc_d2f = 144;
-// private static final int opc_i2b = 145;
-// private static final int opc_i2c = 146;
-// private static final int opc_i2s = 147;
-// private static final int opc_lcmp = 148;
-// private static final int opc_fcmpl = 149;
-// private static final int opc_fcmpg = 150;
-// private static final int opc_dcmpl = 151;
-// private static final int opc_dcmpg = 152;
-// private static final int opc_ifeq = 153;
-// private static final int opc_ifne = 154;
-// private static final int opc_iflt = 155;
-// private static final int opc_ifge = 156;
-// private static final int opc_ifgt = 157;
-// private static final int opc_ifle = 158;
-// private static final int opc_if_icmpeq = 159;
-// private static final int opc_if_icmpne = 160;
-// private static final int opc_if_icmplt = 161;
-// private static final int opc_if_icmpge = 162;
-// private static final int opc_if_icmpgt = 163;
-// private static final int opc_if_icmple = 164;
-// private static final int opc_if_acmpeq = 165;
-// private static final int opc_if_acmpne = 166;
-// private static final int opc_goto = 167;
-// private static final int opc_jsr = 168;
-// private static final int opc_ret = 169;
-// private static final int opc_tableswitch = 170;
-// private static final int opc_lookupswitch = 171;
- private static final int opc_ireturn = 172;
- private static final int opc_lreturn = 173;
- private static final int opc_freturn = 174;
- private static final int opc_dreturn = 175;
- private static final int opc_areturn = 176;
- private static final int opc_return = 177;
- private static final int opc_getstatic = 178;
- private static final int opc_putstatic = 179;
- private static final int opc_getfield = 180;
-// private static final int opc_putfield = 181;
- private static final int opc_invokevirtual = 182;
- private static final int opc_invokespecial = 183;
- private static final int opc_invokestatic = 184;
- private static final int opc_invokeinterface = 185;
- private static final int opc_new = 187;
-// private static final int opc_newarray = 188;
- private static final int opc_anewarray = 189;
-// private static final int opc_arraylength = 190;
- private static final int opc_athrow = 191;
- private static final int opc_checkcast = 192;
-// private static final int opc_instanceof = 193;
-// private static final int opc_monitorenter = 194;
-// private static final int opc_monitorexit = 195;
- private static final int opc_wide = 196;
-// private static final int opc_multianewarray = 197;
-// private static final int opc_ifnull = 198;
-// private static final int opc_ifnonnull = 199;
-// private static final int opc_goto_w = 200;
-// private static final int opc_jsr_w = 201;
-
- // end of constants copied from sun.tools.java.RuntimeConstants
-
- /** name of the superclass of proxy classes */
- private static final String superclassName = "java/lang/reflect/Proxy";
-
- /** name of field for storing a proxy instance's invocation handler */
- private static final String handlerFieldName = "h";
-
- /** debugging flag for saving generated class files */
- private static final boolean saveGeneratedFiles =
- java.security.AccessController.doPrivileged(
- new GetBooleanAction(
- "sun.misc.ProxyGenerator.saveGeneratedFiles")).booleanValue();
-
- /**
- * Generate a public proxy class given a name and a list of proxy interfaces.
- */
- public static byte[] generateProxyClass(final String name,
- Class<?>[] interfaces) {
- return generateProxyClass(name, interfaces, (ACC_PUBLIC | ACC_FINAL | ACC_SUPER));
- }
-
- /**
- * Generate a proxy class given a name and a list of proxy interfaces.
- *
- * @param name the class name of the proxy class
- * @param interfaces proxy interfaces
- * @param accessFlags access flags of the proxy class
- */
- public static byte[] generateProxyClass(final String name,
- Class<?>[] interfaces,
- int accessFlags)
- {
- ProxyGenerator gen = new ProxyGenerator(name, interfaces, accessFlags);
- final byte[] classFile = gen.generateClassFile();
-
- if (saveGeneratedFiles) {
- java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<Void>() {
- public Void run() {
- try {
- int i = name.lastIndexOf('.');
- Path path;
- if (i > 0) {
- Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
- Files.createDirectories(dir);
- path = dir.resolve(name.substring(i+1, name.length()) + ".class");
- } else {
- path = Paths.get(name + ".class");
- }
- Files.write(path, classFile);
- return null;
- } catch (IOException e) {
- throw new InternalError(
- "I/O exception saving generated file: " + e);
- }
- }
- });
- }
-
- return classFile;
- }
-
- /* preloaded Method objects for methods in java.lang.Object */
- private static Method hashCodeMethod;
- private static Method equalsMethod;
- private static Method toStringMethod;
- static {
- try {
- hashCodeMethod = Object.class.getMethod("hashCode");
- equalsMethod =
- Object.class.getMethod("equals", new Class<?>[] { Object.class });
- toStringMethod = Object.class.getMethod("toString");
- } catch (NoSuchMethodException e) {
- throw new NoSuchMethodError(e.getMessage());
- }
- }
-
- /** name of proxy class */
- private String className;
-
- /** proxy interfaces */
- private Class<?>[] interfaces;
-
- /** proxy class access flags */
- private int accessFlags;
-
- /** constant pool of class being generated */
- private ConstantPool cp = new ConstantPool();
-
- /** FieldInfo struct for each field of generated class */
- private List<FieldInfo> fields = new ArrayList<>();
-
- /** MethodInfo struct for each method of generated class */
- private List<MethodInfo> methods = new ArrayList<>();
-
- /**
- * maps method signature string to list of ProxyMethod objects for
- * proxy methods with that signature
- */
- private Map<String, List<ProxyMethod>> proxyMethods = new HashMap<>();
-
- /** count of ProxyMethod objects added to proxyMethods */
- private int proxyMethodCount = 0;
-
- /**
- * Construct a ProxyGenerator to generate a proxy class with the
- * specified name and for the given interfaces.
- *
- * A ProxyGenerator object contains the state for the ongoing
- * generation of a particular proxy class.
- */
- private ProxyGenerator(String className, Class<?>[] interfaces, int accessFlags) {
- this.className = className;
- this.interfaces = interfaces;
- this.accessFlags = accessFlags;
- }
-
- /**
- * Generate a class file for the proxy class. This method drives the
- * class file generation process.
- */
- private byte[] generateClassFile() {
-
- /* ============================================================
- * Step 1: Assemble ProxyMethod objects for all methods to
- * generate proxy dispatching code for.
- */
-
- /*
- * Record that proxy methods are needed for the hashCode, equals,
- * and toString methods of java.lang.Object. This is done before
- * the methods from the proxy interfaces so that the methods from
- * java.lang.Object take precedence over duplicate methods in the
- * proxy interfaces.
- */
- addProxyMethod(hashCodeMethod, Object.class);
- addProxyMethod(equalsMethod, Object.class);
- addProxyMethod(toStringMethod, Object.class);
-
- /*
- * Now record all of the methods from the proxy interfaces, giving
- * earlier interfaces precedence over later ones with duplicate
- * methods.
- */
- for (Class<?> intf : interfaces) {
- for (Method m : intf.getMethods()) {
- addProxyMethod(m, intf);
- }
- }
-
- /*
- * For each set of proxy methods with the same signature,
- * verify that the methods' return types are compatible.
- */
- for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
- checkReturnTypes(sigmethods);
- }
-
- /* ============================================================
- * Step 2: Assemble FieldInfo and MethodInfo structs for all of
- * fields and methods in the class we are generating.
- */
- try {
- methods.add(generateConstructor());
-
- for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
- for (ProxyMethod pm : sigmethods) {
-
- // add static field for method's Method object
- fields.add(new FieldInfo(pm.methodFieldName,
- "Ljava/lang/reflect/Method;",
- ACC_PRIVATE | ACC_STATIC));
-
- // generate code for proxy method and add it
- methods.add(pm.generateMethod());
- }
- }
-
- methods.add(generateStaticInitializer());
-
- } catch (IOException e) {
- throw new InternalError("unexpected I/O Exception", e);
- }
-
- if (methods.size() > 65535) {
- throw new IllegalArgumentException("method limit exceeded");
- }
- if (fields.size() > 65535) {
- throw new IllegalArgumentException("field limit exceeded");
- }
-
- /* ============================================================
- * Step 3: Write the final class file.
- */
-
- /*
- * Make sure that constant pool indexes are reserved for the
- * following items before starting to write the final class file.
- */
- cp.getClass(dotToSlash(className));
- cp.getClass(superclassName);
- for (Class<?> intf: interfaces) {
- cp.getClass(dotToSlash(intf.getName()));
- }
-
- /*
- * Disallow new constant pool additions beyond this point, since
- * we are about to write the final constant pool table.
- */
- cp.setReadOnly();
-
- ByteArrayOutputStream bout = new ByteArrayOutputStream();
- DataOutputStream dout = new DataOutputStream(bout);
-
- try {
- /*
- * Write all the items of the "ClassFile" structure.
- * See JVMS section 4.1.
- */
- // u4 magic;
- dout.writeInt(0xCAFEBABE);
- // u2 minor_version;
- dout.writeShort(CLASSFILE_MINOR_VERSION);
- // u2 major_version;
- dout.writeShort(CLASSFILE_MAJOR_VERSION);
-
- cp.write(dout); // (write constant pool)
-
- // u2 access_flags;
- dout.writeShort(accessFlags);
- // u2 this_class;
- dout.writeShort(cp.getClass(dotToSlash(className)));
- // u2 super_class;
- dout.writeShort(cp.getClass(superclassName));
-
- // u2 interfaces_count;
- dout.writeShort(interfaces.length);
- // u2 interfaces[interfaces_count];
- for (Class<?> intf : interfaces) {
- dout.writeShort(cp.getClass(
- dotToSlash(intf.getName())));
- }
-
- // u2 fields_count;
- dout.writeShort(fields.size());
- // field_info fields[fields_count];
- for (FieldInfo f : fields) {
- f.write(dout);
- }
-
- // u2 methods_count;
- dout.writeShort(methods.size());
- // method_info methods[methods_count];
- for (MethodInfo m : methods) {
- m.write(dout);
- }
-
- // u2 attributes_count;
- dout.writeShort(0); // (no ClassFile attributes for proxy classes)
-
- } catch (IOException e) {
- throw new InternalError("unexpected I/O Exception", e);
- }
-
- return bout.toByteArray();
- }
-
- /**
- * Add another method to be proxied, either by creating a new
- * ProxyMethod object or augmenting an old one for a duplicate
- * method.
- *
- * "fromClass" indicates the proxy interface that the method was
- * found through, which may be different from (a subinterface of)
- * the method's "declaring class". Note that the first Method
- * object passed for a given name and descriptor identifies the
- * Method object (and thus the declaring class) that will be
- * passed to the invocation handler's "invoke" method for a given
- * set of duplicate methods.
- */
- private void addProxyMethod(Method m, Class<?> fromClass) {
- String name = m.getName();
- Class<?>[] parameterTypes = m.getParameterTypes();
- Class<?> returnType = m.getReturnType();
- Class<?>[] exceptionTypes = m.getExceptionTypes();
-
- String sig = name + getParameterDescriptors(parameterTypes);
- List<ProxyMethod> sigmethods = proxyMethods.get(sig);
- if (sigmethods != null) {
- for (ProxyMethod pm : sigmethods) {
- if (returnType == pm.returnType) {
- /*
- * Found a match: reduce exception types to the
- * greatest set of exceptions that can thrown
- * compatibly with the throws clauses of both
- * overridden methods.
- */
- List<Class<?>> legalExceptions = new ArrayList<>();
- collectCompatibleTypes(
- exceptionTypes, pm.exceptionTypes, legalExceptions);
- collectCompatibleTypes(
- pm.exceptionTypes, exceptionTypes, legalExceptions);
- pm.exceptionTypes = new Class<?>[legalExceptions.size()];
- pm.exceptionTypes =
- legalExceptions.toArray(pm.exceptionTypes);
- return;
- }
- }
- } else {
- sigmethods = new ArrayList<>(3);
- proxyMethods.put(sig, sigmethods);
- }
- sigmethods.add(new ProxyMethod(name, parameterTypes, returnType,
- exceptionTypes, fromClass));
- }
-
- /**
- * For a given set of proxy methods with the same signature, check
- * that their return types are compatible according to the Proxy
- * specification.
- *
- * Specifically, if there is more than one such method, then all
- * of the return types must be reference types, and there must be
- * one return type that is assignable to each of the rest of them.
- */
- private static void checkReturnTypes(List<ProxyMethod> methods) {
- /*
- * If there is only one method with a given signature, there
- * cannot be a conflict. This is the only case in which a
- * primitive (or void) return type is allowed.
- */
- if (methods.size() < 2) {
- return;
- }
-
- /*
- * List of return types that are not yet known to be
- * assignable from ("covered" by) any of the others.
- */
- LinkedList<Class<?>> uncoveredReturnTypes = new LinkedList<>();
-
- nextNewReturnType:
- for (ProxyMethod pm : methods) {
- Class<?> newReturnType = pm.returnType;
- if (newReturnType.isPrimitive()) {
- throw new IllegalArgumentException(
- "methods with same signature " +
- getFriendlyMethodSignature(pm.methodName,
- pm.parameterTypes) +
- " but incompatible return types: " +
- newReturnType.getName() + " and others");
- }
- boolean added = false;
-
- /*
- * Compare the new return type to the existing uncovered
- * return types.
- */
- ListIterator<Class<?>> liter = uncoveredReturnTypes.listIterator();
- while (liter.hasNext()) {
- Class<?> uncoveredReturnType = liter.next();
-
- /*
- * If an existing uncovered return type is assignable
- * to this new one, then we can forget the new one.
- */
- if (newReturnType.isAssignableFrom(uncoveredReturnType)) {
- assert !added;
- continue nextNewReturnType;
- }
-
- /*
- * If the new return type is assignable to an existing
- * uncovered one, then should replace the existing one
- * with the new one (or just forget the existing one,
- * if the new one has already be put in the list).
- */
- if (uncoveredReturnType.isAssignableFrom(newReturnType)) {
- // (we can assume that each return type is unique)
- if (!added) {
- liter.set(newReturnType);
- added = true;
- } else {
- liter.remove();
- }
- }
- }
-
- /*
- * If we got through the list of existing uncovered return
- * types without an assignability relationship, then add
- * the new return type to the list of uncovered ones.
- */
- if (!added) {
- uncoveredReturnTypes.add(newReturnType);
- }
- }
-
- /*
- * We shouldn't end up with more than one return type that is
- * not assignable from any of the others.
- */
- if (uncoveredReturnTypes.size() > 1) {
- ProxyMethod pm = methods.get(0);
- throw new IllegalArgumentException(
- "methods with same signature " +
- getFriendlyMethodSignature(pm.methodName, pm.parameterTypes) +
- " but incompatible return types: " + uncoveredReturnTypes);
- }
- }
-
- /**
- * A FieldInfo object contains information about a particular field
- * in the class being generated. The class mirrors the data items of
- * the "field_info" structure of the class file format (see JVMS 4.5).
- */
- private class FieldInfo {
- public int accessFlags;
- public String name;
- public String descriptor;
-
- public FieldInfo(String name, String descriptor, int accessFlags) {
- this.name = name;
- this.descriptor = descriptor;
- this.accessFlags = accessFlags;
-
- /*
- * Make sure that constant pool indexes are reserved for the
- * following items before starting to write the final class file.
- */
- cp.getUtf8(name);
- cp.getUtf8(descriptor);
- }
-
- public void write(DataOutputStream out) throws IOException {
- /*
- * Write all the items of the "field_info" structure.
- * See JVMS section 4.5.
- */
- // u2 access_flags;
- out.writeShort(accessFlags);
- // u2 name_index;
- out.writeShort(cp.getUtf8(name));
- // u2 descriptor_index;
- out.writeShort(cp.getUtf8(descriptor));
- // u2 attributes_count;
- out.writeShort(0); // (no field_info attributes for proxy classes)
- }
- }
-
- /**
- * An ExceptionTableEntry object holds values for the data items of
- * an entry in the "exception_table" item of the "Code" attribute of
- * "method_info" structures (see JVMS 4.7.3).
- */
- private static class ExceptionTableEntry {
- public short startPc;
- public short endPc;
- public short handlerPc;
- public short catchType;
-
- public ExceptionTableEntry(short startPc, short endPc,
- short handlerPc, short catchType)
- {
- this.startPc = startPc;
- this.endPc = endPc;
- this.handlerPc = handlerPc;
- this.catchType = catchType;
- }
- };
-
- /**
- * A MethodInfo object contains information about a particular method
- * in the class being generated. This class mirrors the data items of
- * the "method_info" structure of the class file format (see JVMS 4.6).
- */
- private class MethodInfo {
- public int accessFlags;
- public String name;
- public String descriptor;
- public short maxStack;
- public short maxLocals;
- public ByteArrayOutputStream code = new ByteArrayOutputStream();
- public List<ExceptionTableEntry> exceptionTable =
- new ArrayList<ExceptionTableEntry>();
- public short[] declaredExceptions;
-
- public MethodInfo(String name, String descriptor, int accessFlags) {
- this.name = name;
- this.descriptor = descriptor;
- this.accessFlags = accessFlags;
-
- /*
- * Make sure that constant pool indexes are reserved for the
- * following items before starting to write the final class file.
- */
- cp.getUtf8(name);
- cp.getUtf8(descriptor);
- cp.getUtf8("Code");
- cp.getUtf8("Exceptions");
- }
-
- public void write(DataOutputStream out) throws IOException {
- /*
- * Write all the items of the "method_info" structure.
- * See JVMS section 4.6.
- */
- // u2 access_flags;
- out.writeShort(accessFlags);
- // u2 name_index;
- out.writeShort(cp.getUtf8(name));
- // u2 descriptor_index;
- out.writeShort(cp.getUtf8(descriptor));
- // u2 attributes_count;
- out.writeShort(2); // (two method_info attributes:)
-
- // Write "Code" attribute. See JVMS section 4.7.3.
-
- // u2 attribute_name_index;
- out.writeShort(cp.getUtf8("Code"));
- // u4 attribute_length;
- out.writeInt(12 + code.size() + 8 * exceptionTable.size());
- // u2 max_stack;
- out.writeShort(maxStack);
- // u2 max_locals;
- out.writeShort(maxLocals);
- // u2 code_length;
- out.writeInt(code.size());
- // u1 code[code_length];
- code.writeTo(out);
- // u2 exception_table_length;
- out.writeShort(exceptionTable.size());
- for (ExceptionTableEntry e : exceptionTable) {
- // u2 start_pc;
- out.writeShort(e.startPc);
- // u2 end_pc;
- out.writeShort(e.endPc);
- // u2 handler_pc;
- out.writeShort(e.handlerPc);
- // u2 catch_type;
- out.writeShort(e.catchType);
- }
- // u2 attributes_count;
- out.writeShort(0);
-
- // write "Exceptions" attribute. See JVMS section 4.7.4.
-
- // u2 attribute_name_index;
- out.writeShort(cp.getUtf8("Exceptions"));
- // u4 attributes_length;
- out.writeInt(2 + 2 * declaredExceptions.length);
- // u2 number_of_exceptions;
- out.writeShort(declaredExceptions.length);
- // u2 exception_index_table[number_of_exceptions];
- for (short value : declaredExceptions) {
- out.writeShort(value);
- }
- }
-
- }
-
- /**
- * A ProxyMethod object represents a proxy method in the proxy class
- * being generated: a method whose implementation will encode and
- * dispatch invocations to the proxy instance's invocation handler.
- */
- private class ProxyMethod {
-
- public String methodName;
- public Class<?>[] parameterTypes;
- public Class<?> returnType;
- public Class<?>[] exceptionTypes;
- public Class<?> fromClass;
- public String methodFieldName;
-
- private ProxyMethod(String methodName, Class<?>[] parameterTypes,
- Class<?> returnType, Class<?>[] exceptionTypes,
- Class<?> fromClass)
- {
- this.methodName = methodName;
- this.parameterTypes = parameterTypes;
- this.returnType = returnType;
- this.exceptionTypes = exceptionTypes;
- this.fromClass = fromClass;
- this.methodFieldName = "m" + proxyMethodCount++;
- }
-
- /**
- * Return a MethodInfo object for this method, including generating
- * the code and exception table entry.
- */
- private MethodInfo generateMethod() throws IOException {
- String desc = getMethodDescriptor(parameterTypes, returnType);
- MethodInfo minfo = new MethodInfo(methodName, desc,
- ACC_PUBLIC | ACC_FINAL);
-
- int[] parameterSlot = new int[parameterTypes.length];
- int nextSlot = 1;
- for (int i = 0; i < parameterSlot.length; i++) {
- parameterSlot[i] = nextSlot;
- nextSlot += getWordsPerType(parameterTypes[i]);
- }
- int localSlot0 = nextSlot;
- short pc, tryBegin = 0, tryEnd;
-
- DataOutputStream out = new DataOutputStream(minfo.code);
-
- code_aload(0, out);
-
- out.writeByte(opc_getfield);
- out.writeShort(cp.getFieldRef(
- superclassName,
- handlerFieldName, "Ljava/lang/reflect/InvocationHandler;"));
-
- code_aload(0, out);
-
- out.writeByte(opc_getstatic);
- out.writeShort(cp.getFieldRef(
- dotToSlash(className),
- methodFieldName, "Ljava/lang/reflect/Method;"));
-
- if (parameterTypes.length > 0) {
-
- code_ipush(parameterTypes.length, out);
-
- out.writeByte(opc_anewarray);
- out.writeShort(cp.getClass("java/lang/Object"));
-
- for (int i = 0; i < parameterTypes.length; i++) {
-
- out.writeByte(opc_dup);
-
- code_ipush(i, out);
-
- codeWrapArgument(parameterTypes[i], parameterSlot[i], out);
-
- out.writeByte(opc_aastore);
- }
- } else {
-
- out.writeByte(opc_aconst_null);
- }
-
- out.writeByte(opc_invokeinterface);
- out.writeShort(cp.getInterfaceMethodRef(
- "java/lang/reflect/InvocationHandler",
- "invoke",
- "(Ljava/lang/Object;Ljava/lang/reflect/Method;" +
- "[Ljava/lang/Object;)Ljava/lang/Object;"));
- out.writeByte(4);
- out.writeByte(0);
-
- if (returnType == void.class) {
-
- out.writeByte(opc_pop);
-
- out.writeByte(opc_return);
-
- } else {
-
- codeUnwrapReturnValue(returnType, out);
- }
-
- tryEnd = pc = (short) minfo.code.size();
-
- List<Class<?>> catchList = computeUniqueCatchList(exceptionTypes);
- if (catchList.size() > 0) {
-
- for (Class<?> ex : catchList) {
- minfo.exceptionTable.add(new ExceptionTableEntry(
- tryBegin, tryEnd, pc,
- cp.getClass(dotToSlash(ex.getName()))));
- }
-
- out.writeByte(opc_athrow);
-
- pc = (short) minfo.code.size();
-
- minfo.exceptionTable.add(new ExceptionTableEntry(
- tryBegin, tryEnd, pc, cp.getClass("java/lang/Throwable")));
-
- code_astore(localSlot0, out);
-
- out.writeByte(opc_new);
- out.writeShort(cp.getClass(
- "java/lang/reflect/UndeclaredThrowableException"));
-
- out.writeByte(opc_dup);
-
- code_aload(localSlot0, out);
-
- out.writeByte(opc_invokespecial);
-
- out.writeShort(cp.getMethodRef(
- "java/lang/reflect/UndeclaredThrowableException",
- "<init>", "(Ljava/lang/Throwable;)V"));
-
- out.writeByte(opc_athrow);
- }
-
- if (minfo.code.size() > 65535) {
- throw new IllegalArgumentException("code size limit exceeded");
- }
-
- minfo.maxStack = 10;
- minfo.maxLocals = (short) (localSlot0 + 1);
- minfo.declaredExceptions = new short[exceptionTypes.length];
- for (int i = 0; i < exceptionTypes.length; i++) {
- minfo.declaredExceptions[i] = cp.getClass(
- dotToSlash(exceptionTypes[i].getName()));
- }
-
- return minfo;
- }
-
- /**
- * Generate code for wrapping an argument of the given type
- * whose value can be found at the specified local variable
- * index, in order for it to be passed (as an Object) to the
- * invocation handler's "invoke" method. The code is written
- * to the supplied stream.
- */
- private void codeWrapArgument(Class<?> type, int slot,
- DataOutputStream out)
- throws IOException
- {
- if (type.isPrimitive()) {
- PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
-
- if (type == int.class ||
- type == boolean.class ||
- type == byte.class ||
- type == char.class ||
- type == short.class)
- {
- code_iload(slot, out);
- } else if (type == long.class) {
- code_lload(slot, out);
- } else if (type == float.class) {
- code_fload(slot, out);
- } else if (type == double.class) {
- code_dload(slot, out);
- } else {
- throw new AssertionError();
- }
-
- out.writeByte(opc_invokestatic);
- out.writeShort(cp.getMethodRef(
- prim.wrapperClassName,
- "valueOf", prim.wrapperValueOfDesc));
-
- } else {
-
- code_aload(slot, out);
- }
- }
-
- /**
- * Generate code for unwrapping a return value of the given
- * type from the invocation handler's "invoke" method (as type
- * Object) to its correct type. The code is written to the
- * supplied stream.
- */
- private void codeUnwrapReturnValue(Class<?> type, DataOutputStream out)
- throws IOException
- {
- if (type.isPrimitive()) {
- PrimitiveTypeInfo prim = PrimitiveTypeInfo.get(type);
-
- out.writeByte(opc_checkcast);
- out.writeShort(cp.getClass(prim.wrapperClassName));
-
- out.writeByte(opc_invokevirtual);
- out.writeShort(cp.getMethodRef(
- prim.wrapperClassName,
- prim.unwrapMethodName, prim.unwrapMethodDesc));
-
- if (type == int.class ||
- type == boolean.class ||
- type == byte.class ||
- type == char.class ||
- type == short.class)
- {
- out.writeByte(opc_ireturn);
- } else if (type == long.class) {
- out.writeByte(opc_lreturn);
- } else if (type == float.class) {
- out.writeByte(opc_freturn);
- } else if (type == double.class) {
- out.writeByte(opc_dreturn);
- } else {
- throw new AssertionError();
- }
-
- } else {
-
- out.writeByte(opc_checkcast);
- out.writeShort(cp.getClass(dotToSlash(type.getName())));
-
- out.writeByte(opc_areturn);
- }
- }
-
- /**
- * Generate code for initializing the static field that stores
- * the Method object for this proxy method. The code is written
- * to the supplied stream.
- */
- private void codeFieldInitialization(DataOutputStream out)
- throws IOException
- {
- codeClassForName(fromClass, out);
-
- code_ldc(cp.getString(methodName), out);
-
- code_ipush(parameterTypes.length, out);
-
- out.writeByte(opc_anewarray);
- out.writeShort(cp.getClass("java/lang/Class"));
-
- for (int i = 0; i < parameterTypes.length; i++) {
-
- out.writeByte(opc_dup);
-
- code_ipush(i, out);
-
- if (parameterTypes[i].isPrimitive()) {
- PrimitiveTypeInfo prim =
- PrimitiveTypeInfo.get(parameterTypes[i]);
-
- out.writeByte(opc_getstatic);
- out.writeShort(cp.getFieldRef(
- prim.wrapperClassName, "TYPE", "Ljava/lang/Class;"));
-
- } else {
- codeClassForName(parameterTypes[i], out);
- }
-
- out.writeByte(opc_aastore);
- }
-
- out.writeByte(opc_invokevirtual);
- out.writeShort(cp.getMethodRef(
- "java/lang/Class",
- "getMethod",
- "(Ljava/lang/String;[Ljava/lang/Class;)" +
- "Ljava/lang/reflect/Method;"));
-
- out.writeByte(opc_putstatic);
- out.writeShort(cp.getFieldRef(
- dotToSlash(className),
- methodFieldName, "Ljava/lang/reflect/Method;"));
- }
- }
-
- /**
- * Generate the constructor method for the proxy class.
- */
- private MethodInfo generateConstructor() throws IOException {
- MethodInfo minfo = new MethodInfo(
- "<init>", "(Ljava/lang/reflect/InvocationHandler;)V",
- ACC_PUBLIC);
-
- DataOutputStream out = new DataOutputStream(minfo.code);
-
- code_aload(0, out);
-
- code_aload(1, out);
-
- out.writeByte(opc_invokespecial);
- out.writeShort(cp.getMethodRef(
- superclassName,
- "<init>", "(Ljava/lang/reflect/InvocationHandler;)V"));
-
- out.writeByte(opc_return);
-
- minfo.maxStack = 10;
- minfo.maxLocals = 2;
- minfo.declaredExceptions = new short[0];
-
- return minfo;
- }
-
- /**
- * Generate the static initializer method for the proxy class.
- */
- private MethodInfo generateStaticInitializer() throws IOException {
- MethodInfo minfo = new MethodInfo(
- "<clinit>", "()V", ACC_STATIC);
-
- int localSlot0 = 1;
- short pc, tryBegin = 0, tryEnd;
-
- DataOutputStream out = new DataOutputStream(minfo.code);
-
- for (List<ProxyMethod> sigmethods : proxyMethods.values()) {
- for (ProxyMethod pm : sigmethods) {
- pm.codeFieldInitialization(out);
- }
- }
-
- out.writeByte(opc_return);
-
- tryEnd = pc = (short) minfo.code.size();
-
- minfo.exceptionTable.add(new ExceptionTableEntry(
- tryBegin, tryEnd, pc,
- cp.getClass("java/lang/NoSuchMethodException")));
-
- code_astore(localSlot0, out);
-
- out.writeByte(opc_new);
- out.writeShort(cp.getClass("java/lang/NoSuchMethodError"));
-
- out.writeByte(opc_dup);
-
- code_aload(localSlot0, out);
-
- out.writeByte(opc_invokevirtual);
- out.writeShort(cp.getMethodRef(
- "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
-
- out.writeByte(opc_invokespecial);
- out.writeShort(cp.getMethodRef(
- "java/lang/NoSuchMethodError", "<init>", "(Ljava/lang/String;)V"));
-
- out.writeByte(opc_athrow);
-
- pc = (short) minfo.code.size();
-
- minfo.exceptionTable.add(new ExceptionTableEntry(
- tryBegin, tryEnd, pc,
- cp.getClass("java/lang/ClassNotFoundException")));
-
- code_astore(localSlot0, out);
-
- out.writeByte(opc_new);
- out.writeShort(cp.getClass("java/lang/NoClassDefFoundError"));
-
- out.writeByte(opc_dup);
-
- code_aload(localSlot0, out);
-
- out.writeByte(opc_invokevirtual);
- out.writeShort(cp.getMethodRef(
- "java/lang/Throwable", "getMessage", "()Ljava/lang/String;"));
-
- out.writeByte(opc_invokespecial);
- out.writeShort(cp.getMethodRef(
- "java/lang/NoClassDefFoundError",
- "<init>", "(Ljava/lang/String;)V"));
-
- out.writeByte(opc_athrow);
-
- if (minfo.code.size() > 65535) {
- throw new IllegalArgumentException("code size limit exceeded");
- }
-
- minfo.maxStack = 10;
- minfo.maxLocals = (short) (localSlot0 + 1);
- minfo.declaredExceptions = new short[0];
-
- return minfo;
- }
-
-
- /*
- * =============== Code Generation Utility Methods ===============
- */
-
- /*
- * The following methods generate code for the load or store operation
- * indicated by their name for the given local variable. The code is
- * written to the supplied stream.
- */
-
- private void code_iload(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_iload, opc_iload_0, out);
- }
-
- private void code_lload(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_lload, opc_lload_0, out);
- }
-
- private void code_fload(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_fload, opc_fload_0, out);
- }
-
- private void code_dload(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_dload, opc_dload_0, out);
- }
-
- private void code_aload(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_aload, opc_aload_0, out);
- }
-
-// private void code_istore(int lvar, DataOutputStream out)
-// throws IOException
-// {
-// codeLocalLoadStore(lvar, opc_istore, opc_istore_0, out);
-// }
-
-// private void code_lstore(int lvar, DataOutputStream out)
-// throws IOException
-// {
-// codeLocalLoadStore(lvar, opc_lstore, opc_lstore_0, out);
-// }
-
-// private void code_fstore(int lvar, DataOutputStream out)
-// throws IOException
-// {
-// codeLocalLoadStore(lvar, opc_fstore, opc_fstore_0, out);
-// }
-
-// private void code_dstore(int lvar, DataOutputStream out)
-// throws IOException
-// {
-// codeLocalLoadStore(lvar, opc_dstore, opc_dstore_0, out);
-// }
-
- private void code_astore(int lvar, DataOutputStream out)
- throws IOException
- {
- codeLocalLoadStore(lvar, opc_astore, opc_astore_0, out);
- }
-
- /**
- * Generate code for a load or store instruction for the given local
- * variable. The code is written to the supplied stream.
- *
- * "opcode" indicates the opcode form of the desired load or store
- * instruction that takes an explicit local variable index, and
- * "opcode_0" indicates the corresponding form of the instruction
- * with the implicit index 0.
- */
- private void codeLocalLoadStore(int lvar, int opcode, int opcode_0,
- DataOutputStream out)
- throws IOException
- {
- assert lvar >= 0 && lvar <= 0xFFFF;
- if (lvar <= 3) {
- out.writeByte(opcode_0 + lvar);
- } else if (lvar <= 0xFF) {
- out.writeByte(opcode);
- out.writeByte(lvar & 0xFF);
- } else {
- /*
- * Use the "wide" instruction modifier for local variable
- * indexes that do not fit into an unsigned byte.
- */
- out.writeByte(opc_wide);
- out.writeByte(opcode);
- out.writeShort(lvar & 0xFFFF);
- }
- }
-
- /**
- * Generate code for an "ldc" instruction for the given constant pool
- * index (the "ldc_w" instruction is used if the index does not fit
- * into an unsigned byte). The code is written to the supplied stream.
- */
- private void code_ldc(int index, DataOutputStream out)
- throws IOException
- {
- assert index >= 0 && index <= 0xFFFF;
- if (index <= 0xFF) {
- out.writeByte(opc_ldc);
- out.writeByte(index & 0xFF);
- } else {
- out.writeByte(opc_ldc_w);
- out.writeShort(index & 0xFFFF);
- }
- }
-
- /**
- * Generate code to push a constant integer value on to the operand
- * stack, using the "iconst_<i>", "bipush", or "sipush" instructions
- * depending on the size of the value. The code is written to the
- * supplied stream.
- */
- private void code_ipush(int value, DataOutputStream out)
- throws IOException
- {
- if (value >= -1 && value <= 5) {
- out.writeByte(opc_iconst_0 + value);
- } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
- out.writeByte(opc_bipush);
- out.writeByte(value & 0xFF);
- } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
- out.writeByte(opc_sipush);
- out.writeShort(value & 0xFFFF);
- } else {
- throw new AssertionError();
- }
- }
-
- /**
- * Generate code to invoke the Class.forName with the name of the given
- * class to get its Class object at runtime. The code is written to
- * the supplied stream. Note that the code generated by this method
- * may caused the checked ClassNotFoundException to be thrown.
- */
- private void codeClassForName(Class<?> cl, DataOutputStream out)
- throws IOException
- {
- code_ldc(cp.getString(cl.getName()), out);
-
- out.writeByte(opc_invokestatic);
- out.writeShort(cp.getMethodRef(
- "java/lang/Class",
- "forName", "(Ljava/lang/String;)Ljava/lang/Class;"));
- }
-
-
- /*
- * ==================== General Utility Methods ====================
- */
-
- /**
- * Convert a fully qualified class name that uses '.' as the package
- * separator, the external representation used by the Java language
- * and APIs, to a fully qualified class name that uses '/' as the
- * package separator, the representation used in the class file
- * format (see JVMS section 4.2).
- */
- private static String dotToSlash(String name) {
- return name.replace('.', '/');
- }
-
- /**
- * Return the "method descriptor" string for a method with the given
- * parameter types and return type. See JVMS section 4.3.3.
- */
- private static String getMethodDescriptor(Class<?>[] parameterTypes,
- Class<?> returnType)
- {
- return getParameterDescriptors(parameterTypes) +
- ((returnType == void.class) ? "V" : getFieldType(returnType));
- }
-
- /**
- * Return the list of "parameter descriptor" strings enclosed in
- * parentheses corresponding to the given parameter types (in other
- * words, a method descriptor without a return descriptor). This
- * string is useful for constructing string keys for methods without
- * regard to their return type.
- */
- private static String getParameterDescriptors(Class<?>[] parameterTypes) {
- StringBuilder desc = new StringBuilder("(");
- for (int i = 0; i < parameterTypes.length; i++) {
- desc.append(getFieldType(parameterTypes[i]));
- }
- desc.append(')');
- return desc.toString();
- }
-
- /**
- * Return the "field type" string for the given type, appropriate for
- * a field descriptor, a parameter descriptor, or a return descriptor
- * other than "void". See JVMS section 4.3.2.
- */
- private static String getFieldType(Class<?> type) {
- if (type.isPrimitive()) {
- return PrimitiveTypeInfo.get(type).baseTypeString;
- } else if (type.isArray()) {
- /*
- * According to JLS 20.3.2, the getName() method on Class does
- * return the VM type descriptor format for array classes (only);
- * using that should be quicker than the otherwise obvious code:
- *
- * return "[" + getTypeDescriptor(type.getComponentType());
- */
- return type.getName().replace('.', '/');
- } else {
- return "L" + dotToSlash(type.getName()) + ";";
- }
- }
-
- /**
- * Returns a human-readable string representing the signature of a
- * method with the given name and parameter types.
- */
- private static String getFriendlyMethodSignature(String name,
- Class<?>[] parameterTypes)
- {
- StringBuilder sig = new StringBuilder(name);
- sig.append('(');
- for (int i = 0; i < parameterTypes.length; i++) {
- if (i > 0) {
- sig.append(',');
- }
- Class<?> parameterType = parameterTypes[i];
- int dimensions = 0;
- while (parameterType.isArray()) {
- parameterType = parameterType.getComponentType();
- dimensions++;
- }
- sig.append(parameterType.getName());
- while (dimensions-- > 0) {
- sig.append("[]");
- }
- }
- sig.append(')');
- return sig.toString();
- }
-
- /**
- * Return the number of abstract "words", or consecutive local variable
- * indexes, required to contain a value of the given type. See JVMS
- * section 3.6.1.
- *
- * Note that the original version of the JVMS contained a definition of
- * this abstract notion of a "word" in section 3.4, but that definition
- * was removed for the second edition.
- */
- private static int getWordsPerType(Class<?> type) {
- if (type == long.class || type == double.class) {
- return 2;
- } else {
- return 1;
- }
- }
-
- /**
- * Add to the given list all of the types in the "from" array that
- * are not already contained in the list and are assignable to at
- * least one of the types in the "with" array.
- *
- * This method is useful for computing the greatest common set of
- * declared exceptions from duplicate methods inherited from
- * different interfaces.
- */
- private static void collectCompatibleTypes(Class<?>[] from,
- Class<?>[] with,
- List<Class<?>> list)
- {
- for (Class<?> fc: from) {
- if (!list.contains(fc)) {
- for (Class<?> wc: with) {
- if (wc.isAssignableFrom(fc)) {
- list.add(fc);
- break;
- }
- }
- }
- }
- }
-
- /**
- * Given the exceptions declared in the throws clause of a proxy method,
- * compute the exceptions that need to be caught from the invocation
- * handler's invoke method and rethrown intact in the method's
- * implementation before catching other Throwables and wrapping them
- * in UndeclaredThrowableExceptions.
- *
- * The exceptions to be caught are returned in a List object. Each
- * exception in the returned list is guaranteed to not be a subclass of
- * any of the other exceptions in the list, so the catch blocks for
- * these exceptions may be generated in any order relative to each other.
- *
- * Error and RuntimeException are each always contained by the returned
- * list (if none of their superclasses are contained), since those
- * unchecked exceptions should always be rethrown intact, and thus their
- * subclasses will never appear in the returned list.
- *
- * The returned List will be empty if java.lang.Throwable is in the
- * given list of declared exceptions, indicating that no exceptions
- * need to be caught.
- */
- private static List<Class<?>> computeUniqueCatchList(Class<?>[] exceptions) {
- List<Class<?>> uniqueList = new ArrayList<>();
- // unique exceptions to catch
-
- uniqueList.add(Error.class); // always catch/rethrow these
- uniqueList.add(RuntimeException.class);
-
- nextException:
- for (Class<?> ex: exceptions) {
- if (ex.isAssignableFrom(Throwable.class)) {
- /*
- * If Throwable is declared to be thrown by the proxy method,
- * then no catch blocks are necessary, because the invoke
- * can, at most, throw Throwable anyway.
- */
- uniqueList.clear();
- break;
- } else if (!Throwable.class.isAssignableFrom(ex)) {
- /*
- * Ignore types that cannot be thrown by the invoke method.
- */
- continue;
- }
- /*
- * Compare this exception against the current list of
- * exceptions that need to be caught:
- */
- for (int j = 0; j < uniqueList.size();) {
- Class<?> ex2 = uniqueList.get(j);
- if (ex2.isAssignableFrom(ex)) {
- /*
- * if a superclass of this exception is already on
- * the list to catch, then ignore this one and continue;
- */
- continue nextException;
- } else if (ex.isAssignableFrom(ex2)) {
- /*
- * if a subclass of this exception is on the list
- * to catch, then remove it;
- */
- uniqueList.remove(j);
- } else {
- j++; // else continue comparing.
- }
- }
- // This exception is unique (so far): add it to the list to catch.
- uniqueList.add(ex);
- }
- return uniqueList;
- }
-
- /**
- * A PrimitiveTypeInfo object contains assorted information about
- * a primitive type in its public fields. The struct for a particular
- * primitive type can be obtained using the static "get" method.
- */
- private static class PrimitiveTypeInfo {
-
- /** "base type" used in various descriptors (see JVMS section 4.3.2) */
- public String baseTypeString;
-
- /** name of corresponding wrapper class */
- public String wrapperClassName;
-
- /** method descriptor for wrapper class "valueOf" factory method */
- public String wrapperValueOfDesc;
-
- /** name of wrapper class method for retrieving primitive value */
- public String unwrapMethodName;
-
- /** descriptor of same method */
- public String unwrapMethodDesc;
-
- private static Map<Class<?>,PrimitiveTypeInfo> table = new HashMap<>();
- static {
- add(byte.class, Byte.class);
- add(char.class, Character.class);
- add(double.class, Double.class);
- add(float.class, Float.class);
- add(int.class, Integer.class);
- add(long.class, Long.class);
- add(short.class, Short.class);
- add(boolean.class, Boolean.class);
- }
-
- private static void add(Class<?> primitiveClass, Class<?> wrapperClass) {
- table.put(primitiveClass,
- new PrimitiveTypeInfo(primitiveClass, wrapperClass));
- }
-
- private PrimitiveTypeInfo(Class<?> primitiveClass, Class<?> wrapperClass) {
- assert primitiveClass.isPrimitive();
-
- baseTypeString =
- Array.newInstance(primitiveClass, 0)
- .getClass().getName().substring(1);
- wrapperClassName = dotToSlash(wrapperClass.getName());
- wrapperValueOfDesc =
- "(" + baseTypeString + ")L" + wrapperClassName + ";";
- unwrapMethodName = primitiveClass.getName() + "Value";
- unwrapMethodDesc = "()" + baseTypeString;
- }
-
- public static PrimitiveTypeInfo get(Class<?> cl) {
- return table.get(cl);
- }
- }
-
-
- /**
- * A ConstantPool object represents the constant pool of a class file
- * being generated. This representation of a constant pool is designed
- * specifically for use by ProxyGenerator; in particular, it assumes
- * that constant pool entries will not need to be resorted (for example,
- * by their type, as the Java compiler does), so that the final index
- * value can be assigned and used when an entry is first created.
- *
- * Note that new entries cannot be created after the constant pool has
- * been written to a class file. To prevent such logic errors, a
- * ConstantPool instance can be marked "read only", so that further
- * attempts to add new entries will fail with a runtime exception.
- *
- * See JVMS section 4.4 for more information about the constant pool
- * of a class file.
- */
- private static class ConstantPool {
-
- /**
- * list of constant pool entries, in constant pool index order.
- *
- * This list is used when writing the constant pool to a stream
- * and for assigning the next index value. Note that element 0
- * of this list corresponds to constant pool index 1.
- */
- private List<Entry> pool = new ArrayList<>(32);
-
- /**
- * maps constant pool data of all types to constant pool indexes.
- *
- * This map is used to look up the index of an existing entry for
- * values of all types.
- */
- private Map<Object,Short> map = new HashMap<>(16);
-
- /** true if no new constant pool entries may be added */
- private boolean readOnly = false;
-
- /**
- * Get or assign the index for a CONSTANT_Utf8 entry.
- */
- public short getUtf8(String s) {
- if (s == null) {
- throw new NullPointerException();
- }
- return getValue(s);
- }
-
- /**
- * Get or assign the index for a CONSTANT_Integer entry.
- */
- public short getInteger(int i) {
- return getValue(i);
- }
-
- /**
- * Get or assign the index for a CONSTANT_Float entry.
- */
- public short getFloat(float f) {
- return getValue(new Float(f));
- }
-
- /**
- * Get or assign the index for a CONSTANT_Class entry.
- */
- public short getClass(String name) {
- short utf8Index = getUtf8(name);
- return getIndirect(new IndirectEntry(
- CONSTANT_CLASS, utf8Index));
- }
-
- /**
- * Get or assign the index for a CONSTANT_String entry.
- */
- public short getString(String s) {
- short utf8Index = getUtf8(s);
- return getIndirect(new IndirectEntry(
- CONSTANT_STRING, utf8Index));
- }
-
- /**
- * Get or assign the index for a CONSTANT_FieldRef entry.
- */
- public short getFieldRef(String className,
- String name, String descriptor)
- {
- short classIndex = getClass(className);
- short nameAndTypeIndex = getNameAndType(name, descriptor);
- return getIndirect(new IndirectEntry(
- CONSTANT_FIELD, classIndex, nameAndTypeIndex));
- }
-
- /**
- * Get or assign the index for a CONSTANT_MethodRef entry.
- */
- public short getMethodRef(String className,
- String name, String descriptor)
- {
- short classIndex = getClass(className);
- short nameAndTypeIndex = getNameAndType(name, descriptor);
- return getIndirect(new IndirectEntry(
- CONSTANT_METHOD, classIndex, nameAndTypeIndex));
- }
-
- /**
- * Get or assign the index for a CONSTANT_InterfaceMethodRef entry.
- */
- public short getInterfaceMethodRef(String className, String name,
- String descriptor)
- {
- short classIndex = getClass(className);
- short nameAndTypeIndex = getNameAndType(name, descriptor);
- return getIndirect(new IndirectEntry(
- CONSTANT_INTERFACEMETHOD, classIndex, nameAndTypeIndex));
- }
-
- /**
- * Get or assign the index for a CONSTANT_NameAndType entry.
- */
- public short getNameAndType(String name, String descriptor) {
- short nameIndex = getUtf8(name);
- short descriptorIndex = getUtf8(descriptor);
- return getIndirect(new IndirectEntry(
- CONSTANT_NAMEANDTYPE, nameIndex, descriptorIndex));
- }
-
- /**
- * Set this ConstantPool instance to be "read only".
- *
- * After this method has been called, further requests to get
- * an index for a non-existent entry will cause an InternalError
- * to be thrown instead of creating of the entry.
- */
- public void setReadOnly() {
- readOnly = true;
- }
-
- /**
- * Write this constant pool to a stream as part of
- * the class file format.
- *
- * This consists of writing the "constant_pool_count" and
- * "constant_pool[]" items of the "ClassFile" structure, as
- * described in JVMS section 4.1.
- */
- public void write(OutputStream out) throws IOException {
- DataOutputStream dataOut = new DataOutputStream(out);
-
- // constant_pool_count: number of entries plus one
- dataOut.writeShort(pool.size() + 1);
-
- for (Entry e : pool) {
- e.write(dataOut);
- }
- }
-
- /**
- * Add a new constant pool entry and return its index.
- */
- private short addEntry(Entry entry) {
- pool.add(entry);
- /*
- * Note that this way of determining the index of the
- * added entry is wrong if this pool supports
- * CONSTANT_Long or CONSTANT_Double entries.
- */
- if (pool.size() >= 65535) {
- throw new IllegalArgumentException(
- "constant pool size limit exceeded");
- }
- return (short) pool.size();
- }
-
- /**
- * Get or assign the index for an entry of a type that contains
- * a direct value. The type of the given object determines the
- * type of the desired entry as follows:
- *
- * java.lang.String CONSTANT_Utf8
- * java.lang.Integer CONSTANT_Integer
- * java.lang.Float CONSTANT_Float
- * java.lang.Long CONSTANT_Long
- * java.lang.Double CONSTANT_DOUBLE
- */
- private short getValue(Object key) {
- Short index = map.get(key);
- if (index != null) {
- return index.shortValue();
- } else {
- if (readOnly) {
- throw new InternalError(
- "late constant pool addition: " + key);
- }
- short i = addEntry(new ValueEntry(key));
- map.put(key, i);
- return i;
- }
- }
-
- /**
- * Get or assign the index for an entry of a type that contains
- * references to other constant pool entries.
- */
- private short getIndirect(IndirectEntry e) {
- Short index = map.get(e);
- if (index != null) {
- return index.shortValue();
- } else {
- if (readOnly) {
- throw new InternalError("late constant pool addition");
- }
- short i = addEntry(e);
- map.put(e, i);
- return i;
- }
- }
-
- /**
- * Entry is the abstact superclass of all constant pool entry types
- * that can be stored in the "pool" list; its purpose is to define a
- * common method for writing constant pool entries to a class file.
- */
- private abstract static class Entry {
- public abstract void write(DataOutputStream out)
- throws IOException;
- }
-
- /**
- * ValueEntry represents a constant pool entry of a type that
- * contains a direct value (see the comments for the "getValue"
- * method for a list of such types).
- *
- * ValueEntry objects are not used as keys for their entries in the
- * Map "map", so no useful hashCode or equals methods are defined.
- */
- private static class ValueEntry extends Entry {
- private Object value;
-
- public ValueEntry(Object value) {
- this.value = value;
- }
-
- public void write(DataOutputStream out) throws IOException {
- if (value instanceof String) {
- out.writeByte(CONSTANT_UTF8);
- out.writeUTF((String) value);
- } else if (value instanceof Integer) {
- out.writeByte(CONSTANT_INTEGER);
- out.writeInt(((Integer) value).intValue());
- } else if (value instanceof Float) {
- out.writeByte(CONSTANT_FLOAT);
- out.writeFloat(((Float) value).floatValue());
- } else if (value instanceof Long) {
- out.writeByte(CONSTANT_LONG);
- out.writeLong(((Long) value).longValue());
- } else if (value instanceof Double) {
- out.writeDouble(CONSTANT_DOUBLE);
- out.writeDouble(((Double) value).doubleValue());
- } else {
- throw new InternalError("bogus value entry: " + value);
- }
- }
- }
-
- /**
- * IndirectEntry represents a constant pool entry of a type that
- * references other constant pool entries, i.e., the following types:
- *
- * CONSTANT_Class, CONSTANT_String, CONSTANT_Fieldref,
- * CONSTANT_Methodref, CONSTANT_InterfaceMethodref, and
- * CONSTANT_NameAndType.
- *
- * Each of these entry types contains either one or two indexes of
- * other constant pool entries.
- *
- * IndirectEntry objects are used as the keys for their entries in
- * the Map "map", so the hashCode and equals methods are overridden
- * to allow matching.
- */
- private static class IndirectEntry extends Entry {
- private int tag;
- private short index0;
- private short index1;
-
- /**
- * Construct an IndirectEntry for a constant pool entry type
- * that contains one index of another entry.
- */
- public IndirectEntry(int tag, short index) {
- this.tag = tag;
- this.index0 = index;
- this.index1 = 0;
- }
-
- /**
- * Construct an IndirectEntry for a constant pool entry type
- * that contains two indexes for other entries.
- */
- public IndirectEntry(int tag, short index0, short index1) {
- this.tag = tag;
- this.index0 = index0;
- this.index1 = index1;
- }
-
- public void write(DataOutputStream out) throws IOException {
- out.writeByte(tag);
- out.writeShort(index0);
- /*
- * If this entry type contains two indexes, write
- * out the second, too.
- */
- if (tag == CONSTANT_FIELD ||
- tag == CONSTANT_METHOD ||
- tag == CONSTANT_INTERFACEMETHOD ||
- tag == CONSTANT_NAMEANDTYPE)
- {
- out.writeShort(index1);
- }
- }
-
- public int hashCode() {
- return tag + index0 + index1;
- }
-
- public boolean equals(Object obj) {
- if (obj instanceof IndirectEntry) {
- IndirectEntry other = (IndirectEntry) obj;
- if (tag == other.tag &&
- index0 == other.index0 && index1 == other.index1)
- {
- return true;
- }
- }
- return false;
- }
- }
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/Queue.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, 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.misc;
-
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
-
-/**
- * Queue: implements a simple queue mechanism. Allows for enumeration of the
- * elements.
- *
- * @author Herb Jellinek
- */
-
-public class Queue<T> {
-
- int length = 0;
-
- QueueElement<T> head = null;
- QueueElement<T> tail = null;
-
- public Queue() {
- }
-
- /**
- * Enqueue an object.
- */
- public synchronized void enqueue(T obj) {
-
- QueueElement<T> newElt = new QueueElement<>(obj);
-
- if (head == null) {
- head = newElt;
- tail = newElt;
- length = 1;
- } else {
- newElt.next = head;
- head.prev = newElt;
- head = newElt;
- length++;
- }
- notify();
- }
-
- /**
- * Dequeue the oldest object on the queue. Will wait indefinitely.
- *
- * @return the oldest object on the queue.
- * @exception java.lang.InterruptedException if any thread has
- * interrupted this thread.
- */
- public T dequeue() throws InterruptedException {
- return dequeue(0L);
- }
-
- /**
- * Dequeue the oldest object on the queue.
- * @param timeOut the number of milliseconds to wait for something
- * to arrive.
- *
- * @return the oldest object on the queue.
- * @exception java.lang.InterruptedException if any thread has
- * interrupted this thread.
- */
- public synchronized T dequeue(long timeOut)
- throws InterruptedException {
-
- while (tail == null) {
- wait(timeOut);
- }
- QueueElement<T> elt = tail;
- tail = elt.prev;
- if (tail == null) {
- head = null;
- } else {
- tail.next = null;
- }
- length--;
- return elt.obj;
- }
-
- /**
- * Is the queue empty?
- * @return true if the queue is empty.
- */
- public synchronized boolean isEmpty() {
- return (tail == null);
- }
-
- /**
- * Returns an enumeration of the elements in Last-In, First-Out
- * order. Use the Enumeration methods on the returned object to
- * fetch the elements sequentially.
- */
- public final synchronized Enumeration<T> elements() {
- return new LIFOQueueEnumerator<>(this);
- }
-
- /**
- * Returns an enumeration of the elements in First-In, First-Out
- * order. Use the Enumeration methods on the returned object to
- * fetch the elements sequentially.
- */
- public final synchronized Enumeration<T> reverseElements() {
- return new FIFOQueueEnumerator<>(this);
- }
-
- public synchronized void dump(String msg) {
- System.err.println(">> "+msg);
- System.err.println("["+length+" elt(s); head = "+
- (head == null ? "null" : (head.obj)+"")+
- " tail = "+(tail == null ? "null" : (tail.obj)+""));
- QueueElement<T> cursor = head;
- QueueElement<T> last = null;
- while (cursor != null) {
- System.err.println(" "+cursor);
- last = cursor;
- cursor = cursor.next;
- }
- if (last != tail) {
- System.err.println(" tail != last: "+tail+", "+last);
- }
- System.err.println("]");
- }
-}
-
-final class FIFOQueueEnumerator<T> implements Enumeration<T> {
- Queue<T> queue;
- QueueElement<T> cursor;
-
- FIFOQueueEnumerator(Queue<T> q) {
- queue = q;
- cursor = q.tail;
- }
-
- public boolean hasMoreElements() {
- return (cursor != null);
- }
-
- public T nextElement() {
- synchronized (queue) {
- if (cursor != null) {
- QueueElement<T> result = cursor;
- cursor = cursor.prev;
- return result.obj;
- }
- }
- throw new NoSuchElementException("FIFOQueueEnumerator");
- }
-}
-
-final class LIFOQueueEnumerator<T> implements Enumeration<T> {
- Queue<T> queue;
- QueueElement<T> cursor;
-
- LIFOQueueEnumerator(Queue<T> q) {
- queue = q;
- cursor = q.head;
- }
-
- public boolean hasMoreElements() {
- return (cursor != null);
- }
-
- public T nextElement() {
- synchronized (queue) {
- if (cursor != null) {
- QueueElement<T> result = cursor;
- cursor = cursor.next;
- return result.obj;
- }
- }
- throw new NoSuchElementException("LIFOQueueEnumerator");
- }
-}
-
-class QueueElement<T> {
- QueueElement<T> next = null;
- QueueElement<T> prev = null;
-
- T obj = null;
-
- QueueElement(T obj) {
- this.obj = obj;
- }
-
- public String toString() {
- return "QueueElement[obj="+obj+(prev == null ? " null" : " prev")+
- (next == null ? " null" : " next")+"]";
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/Request.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 1996, 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.misc;
-
-/**
- * Requests are functor objects; that is, they provide part of the mechanism
- * for deferred function application.
- *
- * @author Steven B. Byrne
- */
-
-public abstract class Request {
- /**
- * The main task of the Request object is to be exectuted from a request
- * queue.
- */
- public abstract void execute();
-}
--- a/jdk/src/java.base/share/classes/sun/misc/RequestProcessor.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, 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.misc;
-
-/**
- * The request processor allows functors (Request instances) to be created
- * in arbitrary threads, and to be posted for execution in a non-restricted
- * thread.
- *
- * @author Steven B. Byrne
- */
-
-
-public class RequestProcessor implements Runnable {
-
- private static Queue<Request> requestQueue;
- private static Thread dispatcher;
-
- /**
- * Queues a Request instance for execution by the request procesor
- * thread.
- */
- public static void postRequest(Request req) {
- lazyInitialize();
- requestQueue.enqueue(req);
- }
-
- /**
- * Process requests as they are queued.
- */
- public void run() {
- lazyInitialize();
- while (true) {
- try {
- Request req = requestQueue.dequeue();
- try {
- req.execute();
- } catch (Throwable t) {
- // do nothing at the moment...maybe report an error
- // in the future
- }
- } catch (InterruptedException e) {
- // do nothing at the present time.
- }
- }
- }
-
-
- /**
- * This method initiates the request processor thread. It is safe
- * to call it after the thread has been started. It provides a way for
- * clients to deliberately control the context in which the request
- * processor thread is created
- */
- public static synchronized void startProcessing() {
- if (dispatcher == null) {
- dispatcher = new ManagedLocalsThread(new RequestProcessor(), "Request Processor");
- dispatcher.setPriority(Thread.NORM_PRIORITY + 2);
- dispatcher.start();
- }
- }
-
-
- /**
- * This method performs lazy initialization.
- */
- private static synchronized void lazyInitialize() {
- if (requestQueue == null) {
- requestQueue = new Queue<Request>();
- }
- }
-
-}
--- a/jdk/src/java.base/share/classes/sun/misc/Signal.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/misc/Signal.java Wed Jan 06 14:54:24 2016 +0000
@@ -213,7 +213,7 @@
}
};
if (handler != null) {
- new ManagedLocalsThread(runnable, sig + " handler").start();
+ new Thread(null, runnable, sig + " handler", 0, false).start();
}
}
--- a/jdk/src/java.base/share/classes/sun/misc/UCDecoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 1995, 2000, 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.misc;
-
-import java.io.OutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PushbackInputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a robust character decoder. The decoder will
- * converted encoded text into binary data.
- *
- * The basic encoding unit is a 3 character atom. It encodes two bytes
- * of data. Bytes are encoded into a 64 character set, the characters
- * were chosen specifically because they appear in all codesets.
- * We don't care what their numerical equivalent is because
- * we use a character array to map them. This is like UUencoding
- * with the dependency on ASCII removed.
- *
- * The three chars that make up an atom are encoded as follows:
- * <pre>
- * 00xxxyyy 00axxxxx 00byyyyy
- * 00 = leading zeros, all values are 0 - 63
- * xxxyyy - Top 3 bits of X, Top 3 bits of Y
- * axxxxx - a = X parity bit, xxxxx lower 5 bits of X
- * byyyyy - b = Y parity bit, yyyyy lower 5 bits of Y
- * </pre>
- *
- * The atoms are arranged into lines suitable for inclusion into an
- * email message or text file. The number of bytes that are encoded
- * per line is 48 which keeps the total line length under 80 chars)
- *
- * Each line has the form(
- * <pre>
- * *(LLSS)(DDDD)(DDDD)(DDDD)...(CRC)
- * Where each (xxx) represents a three character atom.
- * (LLSS) - 8 bit length (high byte), and sequence number
- * modulo 256;
- * (DDDD) - Data byte atoms, if length is odd, last data
- * atom has (DD00) (high byte data, low byte 0)
- * (CRC) - 16 bit CRC for the line, includes length,
- * sequence, and all data bytes. If there is a
- * zero pad byte (odd length) it is _NOT_
- * included in the CRC.
- * </pre>
- *
- * If an error is encountered during decoding this class throws a
- * CEFormatException. The specific detail messages are:
- *
- * <pre>
- * "UCDecoder: High byte parity error."
- * "UCDecoder: Low byte parity error."
- * "UCDecoder: Out of sequence line."
- * "UCDecoder: CRC check failed."
- * </pre>
- *
- * @author Chuck McManis
- * @see CharacterEncoder
- * @see UCEncoder
- */
-public class UCDecoder extends CharacterDecoder {
-
- /** This class encodes two bytes per atom. */
- protected int bytesPerAtom() {
- return (2);
- }
-
- /** this class encodes 48 bytes per line */
- protected int bytesPerLine() {
- return (48);
- }
-
- /* this is the UCE mapping of 0-63 to characters .. */
- private static final byte map_array[] = {
- // 0 1 2 3 4 5 6 7
- (byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7', // 0
- (byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F', // 1
- (byte)'G',(byte)'H',(byte)'I',(byte)'J',(byte)'K',(byte)'L',(byte)'M',(byte)'N', // 2
- (byte)'O',(byte)'P',(byte)'Q',(byte)'R',(byte)'S',(byte)'T',(byte)'U',(byte)'V', // 3
- (byte)'W',(byte)'X',(byte)'Y',(byte)'Z',(byte)'a',(byte)'b',(byte)'c',(byte)'d', // 4
- (byte)'e',(byte)'f',(byte)'g',(byte)'h',(byte)'i',(byte)'j',(byte)'k',(byte)'l', // 5
- (byte)'m',(byte)'n',(byte)'o',(byte)'p',(byte)'q',(byte)'r',(byte)'s',(byte)'t', // 6
- (byte)'u',(byte)'v',(byte)'w',(byte)'x',(byte)'y',(byte)'z',(byte)'(',(byte)')' // 7
- };
-
- private int sequence;
- private byte tmp[] = new byte[2];
- private CRC16 crc = new CRC16();
-
- /**
- * Decode one atom - reads the characters from the input stream, decodes
- * them, and checks for valid parity.
- */
- protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int l) throws IOException {
- int i, p1, p2, np1, np2;
- byte a = -1, b = -1, c = -1;
- byte high_byte, low_byte;
- byte tmp[] = new byte[3];
-
- i = inStream.read(tmp);
- if (i != 3) {
- throw new CEStreamExhausted();
- }
- for (i = 0; (i < 64) && ((a == -1) || (b == -1) || (c == -1)); i++) {
- if (tmp[0] == map_array[i]) {
- a = (byte) i;
- }
- if (tmp[1] == map_array[i]) {
- b = (byte) i;
- }
- if (tmp[2] == map_array[i]) {
- c = (byte) i;
- }
- }
- high_byte = (byte) (((a & 0x38) << 2) + (b & 0x1f));
- low_byte = (byte) (((a & 0x7) << 5) + (c & 0x1f));
- p1 = 0;
- p2 = 0;
- for (i = 1; i < 256; i = i * 2) {
- if ((high_byte & i) != 0)
- p1++;
- if ((low_byte & i) != 0)
- p2++;
- }
- np1 = (b & 32) / 32;
- np2 = (c & 32) / 32;
- if ((p1 & 1) != np1) {
- throw new CEFormatException("UCDecoder: High byte parity error.");
- }
- if ((p2 & 1) != np2) {
- throw new CEFormatException("UCDecoder: Low byte parity error.");
- }
- outStream.write(high_byte);
- crc.update(high_byte);
- if (l == 2) {
- outStream.write(low_byte);
- crc.update(low_byte);
- }
- }
-
- private ByteArrayOutputStream lineAndSeq = new ByteArrayOutputStream(2);
-
- /**
- * decodeBufferPrefix initializes the sequence number to zero.
- */
- protected void decodeBufferPrefix(PushbackInputStream inStream, OutputStream outStream) {
- sequence = 0;
- }
-
- /**
- * decodeLinePrefix reads the sequence number and the number of
- * encoded bytes from the line. If the sequence number is not the
- * previous sequence number + 1 then an exception is thrown.
- * UCE lines are line terminator immune, they all start with *
- * so the other thing this method does is scan for the next line
- * by looking for the * character.
- *
- * @exception CEFormatException out of sequence lines detected.
- */
- protected int decodeLinePrefix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int i;
- int nLen, nSeq;
- byte xtmp[];
- int c;
-
- crc.value = 0;
- while (true) {
- c = inStream.read(tmp, 0, 1);
- if (c == -1) {
- throw new CEStreamExhausted();
- }
- if (tmp[0] == '*') {
- break;
- }
- }
- lineAndSeq.reset();
- decodeAtom(inStream, lineAndSeq, 2);
- xtmp = lineAndSeq.toByteArray();
- nLen = xtmp[0] & 0xff;
- nSeq = xtmp[1] & 0xff;
- if (nSeq != sequence) {
- throw new CEFormatException("UCDecoder: Out of sequence line.");
- }
- sequence = (sequence + 1) & 0xff;
- return (nLen);
- }
-
-
- /**
- * this method reads the CRC that is at the end of every line and
- * verifies that it matches the computed CRC.
- *
- * @exception CEFormatException if CRC check fails.
- */
- protected void decodeLineSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int i;
- int lineCRC = crc.value;
- int readCRC;
- byte tmp[];
-
- lineAndSeq.reset();
- decodeAtom(inStream, lineAndSeq, 2);
- tmp = lineAndSeq.toByteArray();
- readCRC = ((tmp[0] << 8) & 0xFF00) + (tmp[1] & 0xff);
- if (readCRC != lineCRC) {
- throw new CEFormatException("UCDecoder: CRC check failed.");
- }
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/UCEncoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 1995, 1997, 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.misc;
-
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a robust character encoder. The encoder is designed
- * to convert binary data into printable characters. The characters are
- * assumed to exist but they are not assumed to be ASCII, the complete set
- * is 0-9, A-Z, a-z, "(", and ")".
- *
- * The basic encoding unit is a 3 character atom. It encodes two bytes
- * of data. Bytes are encoded into a 64 character set, the characters
- * were chosen specifically because they appear in all codesets.
- * We don't care what their numerical equivalent is because
- * we use a character array to map them. This is like UUencoding
- * with the dependency on ASCII removed.
- *
- * The three chars that make up an atom are encoded as follows:
- * <pre>
- * 00xxxyyy 00axxxxx 00byyyyy
- * 00 = leading zeros, all values are 0 - 63
- * xxxyyy - Top 3 bits of X, Top 3 bits of Y
- * axxxxx - a = X parity bit, xxxxx lower 5 bits of X
- * byyyyy - b = Y parity bit, yyyyy lower 5 bits of Y
- * </pre>
- *
- * The atoms are arranged into lines suitable for inclusion into an
- * email message or text file. The number of bytes that are encoded
- * per line is 48 which keeps the total line length under 80 chars)
- *
- * Each line has the form(
- * <pre>
- * *(LLSS)(DDDD)(DDDD)(DDDD)...(CRC)
- * Where each (xxx) represents a three character atom.
- * (LLSS) - 8 bit length (high byte), and sequence number
- * modulo 256;
- * (DDDD) - Data byte atoms, if length is odd, last data
- * atom has (DD00) (high byte data, low byte 0)
- * (CRC) - 16 bit CRC for the line, includes length,
- * sequence, and all data bytes. If there is a
- * zero pad byte (odd length) it is _NOT_
- * included in the CRC.
- * </pre>
- *
- * @author Chuck McManis
- * @see CharacterEncoder
- * @see UCDecoder
- */
-public class UCEncoder extends CharacterEncoder {
-
- /** this clase encodes two bytes per atom */
- protected int bytesPerAtom() {
- return (2);
- }
-
- /** this class encodes 48 bytes per line */
- protected int bytesPerLine() {
- return (48);
- }
-
- /* this is the UCE mapping of 0-63 to characters .. */
- private static final byte map_array[] = {
- // 0 1 2 3 4 5 6 7
- (byte)'0',(byte)'1',(byte)'2',(byte)'3',(byte)'4',(byte)'5',(byte)'6',(byte)'7', // 0
- (byte)'8',(byte)'9',(byte)'A',(byte)'B',(byte)'C',(byte)'D',(byte)'E',(byte)'F', // 1
- (byte)'G',(byte)'H',(byte)'I',(byte)'J',(byte)'K',(byte)'L',(byte)'M',(byte)'N', // 2
- (byte)'O',(byte)'P',(byte)'Q',(byte)'R',(byte)'S',(byte)'T',(byte)'U',(byte)'V', // 3
- (byte)'W',(byte)'X',(byte)'Y',(byte)'Z',(byte)'a',(byte)'b',(byte)'c',(byte)'d', // 4
- (byte)'e',(byte)'f',(byte)'g',(byte)'h',(byte)'i',(byte)'j',(byte)'k',(byte)'l', // 5
- (byte)'m',(byte)'n',(byte)'o',(byte)'p',(byte)'q',(byte)'r',(byte)'s',(byte)'t', // 6
- (byte)'u',(byte)'v',(byte)'w',(byte)'x',(byte)'y',(byte)'z',(byte)'(',(byte)')' // 7
- };
-
- private int sequence;
- private byte tmp[] = new byte[2];
- private CRC16 crc = new CRC16();
-
- /**
- * encodeAtom - take two bytes and encode them into the correct
- * three characters. If only one byte is to be encoded, the other
- * must be zero. The padding byte is not included in the CRC computation.
- */
- protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len) throws IOException
- {
- int i;
- int p1, p2; // parity bits
- byte a, b;
-
- a = data[offset];
- if (len == 2) {
- b = data[offset+1];
- } else {
- b = 0;
- }
- crc.update(a);
- if (len == 2) {
- crc.update(b);
- }
- outStream.write(map_array[((a >>> 2) & 0x38) + ((b >>> 5) & 0x7)]);
- p1 = 0; p2 = 0;
- for (i = 1; i < 256; i = i * 2) {
- if ((a & i) != 0) {
- p1++;
- }
- if ((b & i) != 0) {
- p2++;
- }
- }
- p1 = (p1 & 1) * 32;
- p2 = (p2 & 1) * 32;
- outStream.write(map_array[(a & 31) + p1]);
- outStream.write(map_array[(b & 31) + p2]);
- return;
- }
-
- /**
- * Each UCE encoded line starts with a prefix of '*[XXX]', where
- * the sequence number and the length are encoded in the first
- * atom.
- */
- protected void encodeLinePrefix(OutputStream outStream, int length) throws IOException {
- outStream.write('*');
- crc.value = 0;
- tmp[0] = (byte) length;
- tmp[1] = (byte) sequence;
- sequence = (sequence + 1) & 0xff;
- encodeAtom(outStream, tmp, 0, 2);
- }
-
-
- /**
- * each UCE encoded line ends with YYY and encoded version of the
- * 16 bit checksum. The most significant byte of the check sum
- * is always encoded FIRST.
- */
- protected void encodeLineSuffix(OutputStream outStream) throws IOException {
- tmp[0] = (byte) ((crc.value >>> 8) & 0xff);
- tmp[1] = (byte) (crc.value & 0xff);
- encodeAtom(outStream, tmp, 0, 2);
- super.pStream.println();
- }
-
- /**
- * The buffer prefix code is used to initialize the sequence number
- * to zero.
- */
- protected void encodeBufferPrefix(OutputStream a) throws IOException {
- sequence = 0;
- super.encodeBufferPrefix(a);
- }
-}
--- a/jdk/src/java.base/share/classes/sun/misc/UUDecoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,274 +0,0 @@
-/*
- * Copyright (c) 1995, 2001, 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.misc;
-
-import java.io.PushbackInputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a Berkeley uu character decoder. This decoder
- * was made famous by the uudecode program.
- *
- * The basic character coding is algorithmic, taking 6 bits of binary
- * data and adding it to an ASCII ' ' (space) character. This converts
- * these six bits into a printable representation. Note that it depends
- * on the ASCII character encoding standard for english. Groups of three
- * bytes are converted into 4 characters by treating the three bytes
- * a four 6 bit groups, group 1 is byte 1's most significant six bits,
- * group 2 is byte 1's least significant two bits plus byte 2's four
- * most significant bits. etc.
- *
- * In this encoding, the buffer prefix is:
- * <pre>
- * begin [mode] [filename]
- * </pre>
- *
- * This is followed by one or more lines of the form:
- * <pre>
- * (len)(data)(data)(data) ...
- * </pre>
- * where (len) is the number of bytes on this line. Note that groupings
- * are always four characters, even if length is not a multiple of three
- * bytes. When less than three characters are encoded, the values of the
- * last remaining bytes is undefined and should be ignored.
- *
- * The last line of data in a uuencoded buffer is represented by a single
- * space character. This is translated by the decoding engine to a line
- * length of zero. This is immediately followed by a line which contains
- * the word 'end[newline]'
- *
- * If an error is encountered during decoding this class throws a
- * CEFormatException. The specific detail messages are:
- *
- * <pre>
- * "UUDecoder: No begin line."
- * "UUDecoder: Malformed begin line."
- * "UUDecoder: Short Buffer."
- * "UUDecoder: Bad Line Length."
- * "UUDecoder: Missing 'end' line."
- * </pre>
- *
- * @author Chuck McManis
- * @see CharacterDecoder
- * @see UUEncoder
- */
-public class UUDecoder extends CharacterDecoder {
-
- /**
- * This string contains the name that was in the buffer being decoded.
- */
- public String bufferName;
-
- /**
- * Represents UNIX(tm) mode bits. Generally three octal digits
- * representing read, write, and execute permission of the owner,
- * group owner, and others. They should be interpreted as the bit groups:
- * <pre>
- * (owner) (group) (others)
- * rwx rwx rwx (r = read, w = write, x = execute)
- *</pre>
- *
- */
- public int mode;
-
-
- /**
- * UU encoding specifies 3 bytes per atom.
- */
- protected int bytesPerAtom() {
- return (3);
- }
-
- /**
- * All UU lines have 45 bytes on them, for line length of 15*4+1 or 61
- * characters per line.
- */
- protected int bytesPerLine() {
- return (45);
- }
-
- /** This is used to decode the atoms */
- private byte decoderBuffer[] = new byte[4];
-
- /**
- * Decode a UU atom. Note that if l is less than 3 we don't write
- * the extra bits, however the encoder always encodes 4 character
- * groups even when they are not needed.
- */
- protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int l)
- throws IOException {
- int i, c1, c2, c3, c4;
- int a, b, c;
- StringBuilder x = new StringBuilder();
-
- for (i = 0; i < 4; i++) {
- c1 = inStream.read();
- if (c1 == -1) {
- throw new CEStreamExhausted();
- }
- x.append((char)c1);
- decoderBuffer[i] = (byte) ((c1 - ' ') & 0x3f);
- }
- a = ((decoderBuffer[0] << 2) & 0xfc) | ((decoderBuffer[1] >>> 4) & 3);
- b = ((decoderBuffer[1] << 4) & 0xf0) | ((decoderBuffer[2] >>> 2) & 0xf);
- c = ((decoderBuffer[2] << 6) & 0xc0) | (decoderBuffer[3] & 0x3f);
- outStream.write((byte)(a & 0xff));
- if (l > 1) {
- outStream.write((byte)( b & 0xff));
- }
- if (l > 2) {
- outStream.write((byte)(c&0xff));
- }
- }
-
- /**
- * For uuencoded buffers, the data begins with a line of the form:
- * begin MODE FILENAME
- * This line always starts in column 1.
- */
- protected void decodeBufferPrefix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int c;
- StringBuilder q = new StringBuilder(32);
- String r;
- boolean sawNewLine;
-
- /*
- * This works by ripping through the buffer until it finds a 'begin'
- * line or the end of the buffer.
- */
- sawNewLine = true;
- while (true) {
- c = inStream.read();
- if (c == -1) {
- throw new CEFormatException("UUDecoder: No begin line.");
- }
- if ((c == 'b') && sawNewLine){
- c = inStream.read();
- if (c == 'e') {
- break;
- }
- }
- sawNewLine = (c == '\n') || (c == '\r');
- }
-
- /*
- * Now we think its begin, (we've seen ^be) so verify it here.
- */
- while ((c != '\n') && (c != '\r')) {
- c = inStream.read();
- if (c == -1) {
- throw new CEFormatException("UUDecoder: No begin line.");
- }
- if ((c != '\n') && (c != '\r')) {
- q.append((char)c);
- }
- }
- r = q.toString();
- if (r.indexOf(' ') != 3) {
- throw new CEFormatException("UUDecoder: Malformed begin line.");
- }
- mode = Integer.parseInt(r.substring(4,7));
- bufferName = r.substring(r.indexOf(' ',6)+1);
- /*
- * Check for \n after \r
- */
- if (c == '\r') {
- c = inStream.read ();
- if ((c != '\n') && (c != -1))
- inStream.unread (c);
- }
- }
-
- /**
- * In uuencoded buffers, encoded lines start with a character that
- * represents the number of bytes encoded in this line. The last
- * line of input is always a line that starts with a single space
- * character, which would be a zero length line.
- */
- protected int decodeLinePrefix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int c;
-
- c = inStream.read();
- if (c == ' ') {
- c = inStream.read(); /* discard the (first)trailing CR or LF */
- c = inStream.read(); /* check for a second one */
- if ((c != '\n') && (c != -1))
- inStream.unread (c);
- throw new CEStreamExhausted();
- } else if (c == -1) {
- throw new CEFormatException("UUDecoder: Short Buffer.");
- }
-
- c = (c - ' ') & 0x3f;
- if (c > bytesPerLine()) {
- throw new CEFormatException("UUDecoder: Bad Line Length.");
- }
- return (c);
- }
-
-
- /**
- * Find the end of the line for the next operation.
- * The following sequences are recognized as end-of-line
- * CR, CR LF, or LF
- */
- protected void decodeLineSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int c;
- while (true) {
- c = inStream.read();
- if (c == -1) {
- throw new CEStreamExhausted();
- }
- if (c == '\n') {
- break;
- }
- if (c == '\r') {
- c = inStream.read();
- if ((c != '\n') && (c != -1)) {
- inStream.unread (c);
- }
- break;
- }
- }
- }
-
- /**
- * UUencoded files have a buffer suffix which consists of the word
- * end. This line should immediately follow the line with a single
- * space in it.
- */
- protected void decodeBufferSuffix(PushbackInputStream inStream, OutputStream outStream) throws IOException {
- int c;
-
- c = inStream.read(decoderBuffer);
- if ((decoderBuffer[0] != 'e') || (decoderBuffer[1] != 'n') ||
- (decoderBuffer[2] != 'd')) {
- throw new CEFormatException("UUDecoder: Missing 'end' line.");
- }
- }
-
-}
--- a/jdk/src/java.base/share/classes/sun/misc/UUEncoder.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/*
- * Copyright (c) 1995, 2004, 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.misc;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.IOException;
-
-/**
- * This class implements a Berkeley uu character encoder. This encoder
- * was made famous by uuencode program.
- *
- * The basic character coding is algorithmic, taking 6 bits of binary
- * data and adding it to an ASCII ' ' (space) character. This converts
- * these six bits into a printable representation. Note that it depends
- * on the ASCII character encoding standard for english. Groups of three
- * bytes are converted into 4 characters by treating the three bytes
- * a four 6 bit groups, group 1 is byte 1's most significant six bits,
- * group 2 is byte 1's least significant two bits plus byte 2's four
- * most significant bits. etc.
- *
- * In this encoding, the buffer prefix is:
- * <pre>
- * begin [mode] [filename]
- * </pre>
- *
- * This is followed by one or more lines of the form:
- * <pre>
- * (len)(data)(data)(data) ...
- * </pre>
- * where (len) is the number of bytes on this line. Note that groupings
- * are always four characters, even if length is not a multiple of three
- * bytes. When less than three characters are encoded, the values of the
- * last remaining bytes is undefined and should be ignored.
- *
- * The last line of data in a uuencoded file is represented by a single
- * space character. This is translated by the decoding engine to a line
- * length of zero. This is immediately followed by a line which contains
- * the word 'end[newline]'
- *
- * @author Chuck McManis
- * @see CharacterEncoder
- * @see UUDecoder
- */
-public class UUEncoder extends CharacterEncoder {
-
- /**
- * This name is stored in the begin line.
- */
- private String bufferName;
-
- /**
- * Represents UNIX(tm) mode bits. Generally three octal digits representing
- * read, write, and execute permission of the owner, group owner, and
- * others. They should be interpreted as the bit groups:
- * (owner) (group) (others)
- * rwx rwx rwx (r = read, w = write, x = execute)
- *
- * By default these are set to 644 (UNIX rw-r--r-- permissions).
- */
- private int mode;
-
-
- /**
- * Default - buffer begin line will be:
- * <pre>
- * begin 644 encoder.buf
- * </pre>
- */
- public UUEncoder() {
- bufferName = "encoder.buf";
- mode = 644;
- }
-
- /**
- * Specifies a name for the encoded buffer, begin line will be:
- * <pre>
- * begin 644 [FNAME]
- * </pre>
- */
- public UUEncoder(String fname) {
- bufferName = fname;
- mode = 644;
- }
-
- /**
- * Specifies a name and mode for the encoded buffer, begin line will be:
- * <pre>
- * begin [MODE] [FNAME]
- * </pre>
- */
- public UUEncoder(String fname, int newMode) {
- bufferName = fname;
- mode = newMode;
- }
-
- /** number of bytes per atom in uuencoding is 3 */
- protected int bytesPerAtom() {
- return (3);
- }
-
- /** number of bytes per line in uuencoding is 45 */
- protected int bytesPerLine() {
- return (45);
- }
-
- /**
- * encodeAtom - take three bytes and encodes them into 4 characters
- * If len is less than 3 then remaining bytes are filled with '1'.
- * This insures that the last line won't end in spaces and potentiallly
- * be truncated.
- */
- protected void encodeAtom(OutputStream outStream, byte data[], int offset, int len)
- throws IOException {
- byte a, b = 1, c = 1;
- int c1, c2, c3, c4;
-
- a = data[offset];
- if (len > 1) {
- b = data[offset+1];
- }
- if (len > 2) {
- c = data[offset+2];
- }
-
- c1 = (a >>> 2) & 0x3f;
- c2 = ((a << 4) & 0x30) | ((b >>> 4) & 0xf);
- c3 = ((b << 2) & 0x3c) | ((c >>> 6) & 0x3);
- c4 = c & 0x3f;
- outStream.write(c1 + ' ');
- outStream.write(c2 + ' ');
- outStream.write(c3 + ' ');
- outStream.write(c4 + ' ');
- return;
- }
-
- /**
- * Encode the line prefix which consists of the single character. The
- * lenght is added to the value of ' ' (32 decimal) and printed.
- */
- protected void encodeLinePrefix(OutputStream outStream, int length)
- throws IOException {
- outStream.write((length & 0x3f) + ' ');
- }
-
-
- /**
- * The line suffix for uuencoded files is simply a new line.
- */
- protected void encodeLineSuffix(OutputStream outStream) throws IOException {
- pStream.println();
- }
-
- /**
- * encodeBufferPrefix writes the begin line to the output stream.
- */
- protected void encodeBufferPrefix(OutputStream a) throws IOException {
- super.pStream = new PrintStream(a);
- super.pStream.print("begin "+mode+" ");
- if (bufferName != null) {
- super.pStream.println(bufferName);
- } else {
- super.pStream.println("encoder.bin");
- }
- super.pStream.flush();
- }
-
- /**
- * encodeBufferSuffix writes the single line containing space (' ') and
- * the line containing the word 'end' to the output stream.
- */
- protected void encodeBufferSuffix(OutputStream a) throws IOException {
- super.pStream.println(" \nend");
- super.pStream.flush();
- }
-
-}
--- a/jdk/src/java.base/share/classes/sun/misc/VM.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/misc/VM.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,9 +27,6 @@
import static java.lang.Thread.State.*;
import java.util.Properties;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
public class VM {
@@ -274,9 +271,6 @@
// used by java.lang.Integer.IntegerCache
props.remove("java.lang.Integer.IntegerCache.high");
- // used by java.util.zip.ZipFile
- props.remove("sun.zip.disableMemoryMapping");
-
// used by sun.launcher.LauncherHelper
props.remove("sun.java.launcher.diag");
}
@@ -291,10 +285,10 @@
}
/* Current count of objects pending for finalization */
- private static volatile int finalRefCount = 0;
+ private static volatile int finalRefCount;
/* Peak count of objects pending for finalization */
- private static volatile int peakFinalRefCount = 0;
+ private static volatile int peakFinalRefCount;
/*
* Gets the number of objects pending for finalization.
--- a/jdk/src/java.base/share/classes/sun/net/NetworkServer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/net/NetworkServer.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,7 +27,6 @@
import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;
-import sun.misc.ManagedLocalsThread;
/**
* This is the base class for network servers. To define a new type
@@ -73,7 +72,7 @@
NetworkServer n = (NetworkServer)clone();
n.serverSocket = null;
n.clientSocket = ns;
- new ManagedLocalsThread(n).start();
+ new Thread(null, n, "NetworkServer", 0, false).start();
} catch(Exception e) {
System.out.print("Server failure\n");
e.printStackTrace();
@@ -108,7 +107,7 @@
for each new connection. */
public final void startServer(int port) throws IOException {
serverSocket = new ServerSocket(port, 50);
- serverInstance = new ManagedLocalsThread(this);
+ serverInstance = new Thread(null, this, "NetworkServer", 0, false);
serverInstance.start();
}
--- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,9 +27,8 @@
import java.net.URL;
import java.io.*;
import java.util.StringTokenizer;
-import sun.misc.ManagedLocalsThread;
-class MimeLauncher extends ManagedLocalsThread {
+class MimeLauncher extends Thread {
java.net.URLConnection uc;
MimeEntry m;
String genericTempFileTemplate;
@@ -38,7 +37,7 @@
MimeLauncher (MimeEntry M, java.net.URLConnection uc,
InputStream is, String tempFileTemplate, String threadName) throws ApplicationLaunchException {
- super(threadName);
+ super(null, null, threadName, 0, false);
m = M;
this.uc = uc;
this.is = is;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpCapture.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpCapture.java Wed Jan 06 14:54:24 2016 +0000
@@ -54,12 +54,12 @@
* @author jccollet
*/
public class HttpCapture {
- private File file = null;
+ private File file;
private boolean incoming = true;
- private BufferedWriter out = null;
- private static boolean initialized = false;
- private static volatile ArrayList<Pattern> patterns = null;
- private static volatile ArrayList<String> capFiles = null;
+ private BufferedWriter out;
+ private static boolean initialized;
+ private static volatile ArrayList<Pattern> patterns;
+ private static volatile ArrayList<String> capFiles;
private static synchronized void init() {
initialized = true;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Wed Jan 06 14:54:24 2016 +0000
@@ -98,7 +98,7 @@
// from previous releases.
private static boolean retryPostProp = true;
- volatile boolean keepingAlive = false; /* this is a keep-alive connection */
+ volatile boolean keepingAlive; /* this is a keep-alive connection */
int keepAliveConnections = -1; /* number of keep-alives left */
/**Idle timeout value, in milliseconds. Zero means infinity,
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -51,14 +51,14 @@
protected final FileDescriptor fd;
// the local address to which the channel's socket is bound
- protected volatile InetSocketAddress localAddress = null;
+ protected volatile InetSocketAddress localAddress;
// need this lock to set local address
private final Object stateLock = new Object();
// close support
private ReadWriteLock closeLock = new ReentrantReadWriteLock();
- private volatile boolean open = true;
+ private volatile boolean closed;
// set true when accept operation is cancelled
private volatile boolean acceptKilled;
@@ -73,7 +73,7 @@
@Override
public final boolean isOpen() {
- return open;
+ return !closed;
}
/**
@@ -102,9 +102,9 @@
// synchronize with any threads using file descriptor/handle
closeLock.writeLock().lock();
try {
- if (!open)
+ if (closed)
return; // already closed
- open = false;
+ closed = true;
} finally {
closeLock.writeLock().unlock();
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -54,8 +54,8 @@
// protects state, localAddress, and remoteAddress
protected final Object stateLock = new Object();
- protected volatile InetSocketAddress localAddress = null;
- protected volatile InetSocketAddress remoteAddress = null;
+ protected volatile InetSocketAddress localAddress;
+ protected volatile InetSocketAddress remoteAddress;
// State, increases monotonically
static final int ST_UNINITIALIZED = -1;
@@ -78,7 +78,7 @@
// close support
private final ReadWriteLock closeLock = new ReentrantReadWriteLock();
- private volatile boolean open = true;
+ private volatile boolean closed;
// set true when exclusive binding is on and SO_REUSEADDR is emulated
private boolean isReuseAddress;
@@ -106,7 +106,7 @@
@Override
public final boolean isOpen() {
- return open;
+ return !closed;
}
/**
@@ -135,9 +135,9 @@
// synchronize with any threads initiating asynchronous operations
closeLock.writeLock().lock();
try {
- if (!open)
+ if (closed)
return; // already closed
- open = false;
+ closed = true;
} finally {
closeLock.writeLock().unlock();
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -58,8 +58,8 @@
private final ProtocolFamily family;
// IDs of native threads doing reads and writes, for signalling
- private volatile long readerThread = 0;
- private volatile long writerThread = 0;
+ private volatile long readerThread;
+ private volatile long writerThread;
// Cached InetAddress and port for unconnected DatagramChannels
// used by receive0
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java Wed Jan 06 14:54:24 2016 +0000
@@ -46,7 +46,7 @@
private final DatagramChannelImpl dc;
// Timeout "option" value for receives
- private volatile int timeout = 0;
+ private volatile int timeout;
// ## super will create a useless impl
private DatagramSocketAdaptor(DatagramChannelImpl dc) throws IOException {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileLockImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileLockImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,7 @@
public class FileLockImpl
extends FileLock
{
- private volatile boolean valid = true;
+ private volatile boolean invalid;
FileLockImpl(FileChannel channel, long position, long size, boolean shared)
{
@@ -44,25 +44,25 @@
}
public boolean isValid() {
- return valid;
+ return !invalid;
}
void invalidate() {
assert Thread.holdsLock(this);
- valid = false;
+ invalid = true;
}
public synchronized void release() throws IOException {
Channel ch = acquiredBy();
if (!ch.isOpen())
throw new ClosedChannelException();
- if (valid) {
+ if (isValid()) {
if (ch instanceof FileChannelImpl)
((FileChannelImpl)ch).release(this);
else if (ch instanceof AsynchronousFileChannelImpl)
((AsynchronousFileChannelImpl)ch).release(this);
else throw new AssertionError();
- valid = false;
+ invalidate();
}
}
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/MembershipKeyImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/MembershipKeyImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,8 +43,7 @@
private final NetworkInterface interf;
private final InetAddress source;
- // true when key is valid
- private volatile boolean valid = true;
+ private volatile boolean invalid;
// lock used when creating or accessing blockedSet
private Object stateLock = new Object();
@@ -134,12 +133,12 @@
}
public boolean isValid() {
- return valid;
+ return !invalid;
}
// package-private
void invalidate() {
- valid = false;
+ invalid = true;
}
public void drop() {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,6 @@
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
import sun.net.ExtendedOptionsImpl;
@@ -55,7 +54,7 @@
// -- Miscellaneous utilities --
- private static volatile boolean checkedIPv6 = false;
+ private static volatile boolean checkedIPv6;
private static volatile boolean isIPv6Available;
/**
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketAdaptor.java Wed Jan 06 14:54:24 2016 +0000
@@ -45,7 +45,7 @@
private final ServerSocketChannelImpl ssc;
// Timeout "option" value for accepts
- private volatile int timeout = 0;
+ private volatile int timeout;
public static ServerSocket create(ServerSocketChannelImpl ssc) {
try {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -54,7 +54,7 @@
private int fdVal;
// ID of native thread currently blocked in this channel, for signalling
- private volatile long thread = 0;
+ private volatile long thread;
// Lock held by thread currently blocked in this channel
private final Object lock = new Object();
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketAdaptor.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,13 +26,11 @@
package sun.nio.ch;
import java.io.*;
-import java.lang.ref.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
-import java.util.*;
// Make a socket channel look like a socket.
@@ -55,7 +53,7 @@
private final SocketChannelImpl sc;
// Timeout "option" value for reads
- private volatile int timeout = 0;
+ private volatile int timeout;
private SocketAdaptor(SocketChannelImpl sc) throws SocketException {
super((SocketImpl) null);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -56,8 +56,8 @@
private final int fdVal;
// IDs of native threads doing reads and writes, for signalling
- private volatile long readerThread = 0;
- private volatile long writerThread = 0;
+ private volatile long readerThread;
+ private volatile long writerThread;
// Lock held by current reading or connecting thread
private final Object readLock = new Object();
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,13 +25,10 @@
package sun.nio.ch;
-import java.lang.ref.SoftReference;
import java.lang.reflect.*;
-import java.io.IOException;
import java.io.FileDescriptor;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
-import java.nio.channels.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
@@ -295,7 +292,7 @@
return pageSize;
}
- private static volatile Constructor<?> directByteBufferConstructor = null;
+ private static volatile Constructor<?> directByteBufferConstructor;
private static void initDBBConstructor() {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@@ -340,7 +337,7 @@
return dbb;
}
- private static volatile Constructor<?> directByteBufferRConstructor = null;
+ private static volatile Constructor<?> directByteBufferRConstructor;
private static void initDBBRConstructor() {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@@ -388,7 +385,7 @@
// -- Bug compatibility --
- private static volatile String bugLevel = null;
+ private static volatile String bugLevel;
static boolean atBugLevel(String bl) { // package-private
if (bugLevel == null) {
--- a/jdk/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/StreamDecoder.java Wed Jan 06 14:54:24 2016 +0000
@@ -39,10 +39,10 @@
private static final int MIN_BYTE_BUFFER_SIZE = 32;
private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;
- private volatile boolean isOpen = true;
+ private volatile boolean closed;
private void ensureOpen() throws IOException {
- if (!isOpen)
+ if (closed)
throw new IOException("Stream closed");
}
@@ -188,15 +188,15 @@
public void close() throws IOException {
synchronized (lock) {
- if (!isOpen)
+ if (closed)
return;
implClose();
- isOpen = false;
+ closed = true;
}
}
private boolean isOpen() {
- return isOpen;
+ return !closed;
}
--- a/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/cs/StreamEncoder.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,10 +38,10 @@
private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;
- private volatile boolean isOpen = true;
+ private volatile boolean closed;
private void ensureOpen() throws IOException {
- if (!isOpen)
+ if (closed)
throw new IOException("Stream closed");
}
@@ -156,15 +156,15 @@
public void close() throws IOException {
synchronized (lock) {
- if (!isOpen)
+ if (closed)
return;
implClose();
- isOpen = false;
+ closed = true;
}
}
private boolean isOpen() {
- return isOpen;
+ return !closed;
}
--- a/jdk/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/AbstractPoller.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,6 @@
import java.security.PrivilegedAction;
import java.io.IOException;
import java.util.*;
-import sun.misc.ManagedLocalsThread;
/**
* Base implementation of background poller thread used in watch service
@@ -60,7 +59,7 @@
AccessController.doPrivileged(new PrivilegedAction<>() {
@Override
public Object run() {
- Thread thr = new ManagedLocalsThread(thisRunnable);
+ Thread thr = new Thread(null, thisRunnable, "FileSystemWatchService", 0, false);
thr.setDaemon(true);
thr.start();
return null;
--- a/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/Cancellable.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,7 +25,6 @@
package sun.nio.fs;
-import sun.misc.ManagedLocalsThread;
import jdk.internal.misc.Unsafe;
import java.util.concurrent.ExecutionException;
@@ -118,7 +117,7 @@
* thread by writing into the memory location that it polls cooperatively.
*/
static void runInterruptibly(Cancellable task) throws ExecutionException {
- Thread t = new ManagedLocalsThread(task);
+ Thread t = new Thread(null, task, "NIO-Task", 0, false);
t.start();
boolean cancelledByInterrupt = false;
while (t.isAlive()) {
--- a/jdk/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java Wed Jan 06 14:54:24 2016 +0000
@@ -35,7 +35,6 @@
import java.util.*;
import java.util.concurrent.*;
import com.sun.nio.file.SensitivityWatchEventModifier;
-import sun.misc.ManagedLocalsThread;
/**
* Simple WatchService implementation that uses periodic tasks to poll
@@ -59,7 +58,7 @@
.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
- Thread t = new ManagedLocalsThread(r);
+ Thread t = new Thread(null, r, "FileSystemWatchService", 0, false);
t.setDaemon(true);
return t;
}});
--- a/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,9 +44,9 @@
// Only used if forSerialization is true
private static final short NUM_SERIALIZATION_CPOOL_ENTRIES = (short) 2;
- private static volatile int methodSymnum = 0;
- private static volatile int constructorSymnum = 0;
- private static volatile int serializationConstructorSymnum = 0;
+ private static volatile int methodSymnum;
+ private static volatile int constructorSymnum;
+ private static volatile int serializationConstructorSymnum;
private Class<?> declaringClass;
private Class<?>[] parameterTypes;
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotatedTypeFactory.java Wed Jan 06 14:54:24 2016 +0000
@@ -62,7 +62,7 @@
decl);
if (type instanceof Class) {
return new AnnotatedTypeBaseImpl(type,
- addNesting(type, currentLoc),
+ currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
@@ -74,7 +74,7 @@
decl);
} else if (type instanceof ParameterizedType) {
return new AnnotatedParameterizedTypeImpl((ParameterizedType)type,
- addNesting(type, currentLoc),
+ currentLoc,
actualTypeAnnos,
allOnSameTarget,
decl);
@@ -88,7 +88,7 @@
throw new AssertionError("Unknown instance of Type: " + type + "\nThis should not happen.");
}
- private static LocationInfo addNesting(Type type, LocationInfo addTo) {
+ public static LocationInfo nestingForType(Type type, LocationInfo addTo) {
if (isArray(type))
return addTo;
if (type instanceof Class) {
@@ -96,13 +96,13 @@
if (clz.getEnclosingClass() == null)
return addTo;
if (Modifier.isStatic(clz.getModifiers()))
- return addNesting(clz.getEnclosingClass(), addTo);
- return addNesting(clz.getEnclosingClass(), addTo.pushInner());
+ return nestingForType(clz.getEnclosingClass(), addTo);
+ return nestingForType(clz.getEnclosingClass(), addTo.pushInner());
} else if (type instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType)type;
if (t.getOwnerType() == null)
return addTo;
- return addNesting(t.getOwnerType(), addTo.pushInner());
+ return nestingForType(t.getOwnerType(), addTo.pushInner());
}
return addTo;
}
@@ -118,8 +118,9 @@
return false;
}
+ static final TypeAnnotation[] EMPTY_TYPE_ANNOTATION_ARRAY = new TypeAnnotation[0];
static final AnnotatedType EMPTY_ANNOTATED_TYPE = new AnnotatedTypeBaseImpl(null, LocationInfo.BASE_LOCATION,
- new TypeAnnotation[0], new TypeAnnotation[0], null);
+ EMPTY_TYPE_ANNOTATION_ARRAY, EMPTY_TYPE_ANNOTATION_ARRAY, null);
static final AnnotatedType[] EMPTY_ANNOTATED_TYPE_ARRAY = new AnnotatedType[0];
private static class AnnotatedTypeBaseImpl implements AnnotatedType {
@@ -177,6 +178,30 @@
return type;
}
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ if (!(type instanceof Class<?>))
+ throw new IllegalStateException("Can't compute owner");
+
+ Class<?> inner = (Class<?>)type;
+ Class<?> owner = inner.getDeclaringClass();
+ if (owner == null) // top-level, local or anonymous
+ return null;
+ if (inner.isPrimitive() || inner == Void.TYPE)
+ return null;
+
+ LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
+ TypeAnnotation[]all = getTypeAnnotations();
+ List<TypeAnnotation> l = new ArrayList<>(all.length);
+
+ for (TypeAnnotation t : all)
+ if (t.getLocationInfo().isSameLocationInfo(outerLoc))
+ l.add(t);
+
+ return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
+
+ }
+
// Implementation details
final LocationInfo getLocation() {
return location;
@@ -198,11 +223,17 @@
@Override
public AnnotatedType getAnnotatedGenericComponentType() {
- return AnnotatedTypeFactory.buildAnnotatedType(getComponentType(),
- getLocation().pushArray(),
- getTypeAnnotations(),
- getTypeAnnotations(),
- getDecl());
+ Type t = getComponentType();
+ return AnnotatedTypeFactory.buildAnnotatedType(t,
+ nestingForType(t, getLocation().pushArray()),
+ getTypeAnnotations(),
+ getTypeAnnotations(),
+ getDecl());
+ }
+
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ return null;
}
private Type getComponentType() {
@@ -227,6 +258,11 @@
return getTypeVariable().getAnnotatedBounds();
}
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ return null;
+ }
+
private TypeVariable<?> getTypeVariable() {
return (TypeVariable)getType();
}
@@ -248,19 +284,35 @@
int initialCapacity = getTypeAnnotations().length;
for (int i = 0; i < res.length; i++) {
List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
- LocationInfo newLoc = getLocation().pushTypeArg((byte)i);
+ LocationInfo newLoc = nestingForType(arguments[i], getLocation().pushTypeArg((byte)i));
for (TypeAnnotation t : getTypeAnnotations())
if (t.getLocationInfo().isSameLocationInfo(newLoc))
l.add(t);
res[i] = buildAnnotatedType(arguments[i],
- newLoc,
- l.toArray(new TypeAnnotation[0]),
- getTypeAnnotations(),
- getDecl());
+ newLoc,
+ l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
+ getTypeAnnotations(),
+ getDecl());
}
return res;
}
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ Type owner = getParameterizedType().getOwnerType();
+ if (owner == null)
+ return null;
+ LocationInfo outerLoc = nestingForType(owner, getLocation().popAllLocations((byte)1));
+ TypeAnnotation[]all = getTypeAnnotations();
+ List<TypeAnnotation> l = new ArrayList<>(all.length);
+
+ for (TypeAnnotation t : all)
+ if (t.getLocationInfo().isSameLocationInfo(outerLoc))
+ l.add(t);
+
+ return buildAnnotatedType(owner, outerLoc, l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY), all, getDecl());
+ }
+
private ParameterizedType getParameterizedType() {
return (ParameterizedType)getType();
}
@@ -279,11 +331,11 @@
public AnnotatedType[] getAnnotatedUpperBounds() {
if (!hasUpperBounds()) {
return new AnnotatedType[] { buildAnnotatedType(Object.class,
- LocationInfo.BASE_LOCATION,
- new TypeAnnotation[0],
- new TypeAnnotation[0],
- null)
- };
+ LocationInfo.BASE_LOCATION,
+ EMPTY_TYPE_ANNOTATION_ARRAY,
+ EMPTY_TYPE_ANNOTATION_ARRAY,
+ null)
+ };
}
return getAnnotatedBounds(getWildcardType().getUpperBounds());
}
@@ -295,21 +347,26 @@
return getAnnotatedBounds(getWildcardType().getLowerBounds());
}
+ @Override
+ public AnnotatedType getAnnotatedOwnerType() {
+ return null;
+ }
+
private AnnotatedType[] getAnnotatedBounds(Type[] bounds) {
AnnotatedType[] res = new AnnotatedType[bounds.length];
Arrays.fill(res, EMPTY_ANNOTATED_TYPE);
- LocationInfo newLoc = getLocation().pushWildcard();
int initialCapacity = getTypeAnnotations().length;
for (int i = 0; i < res.length; i++) {
+ LocationInfo newLoc = nestingForType(bounds[i], getLocation().pushWildcard());
List<TypeAnnotation> l = new ArrayList<>(initialCapacity);
for (TypeAnnotation t : getTypeAnnotations())
if (t.getLocationInfo().isSameLocationInfo(newLoc))
l.add(t);
res[i] = buildAnnotatedType(bounds[i],
- newLoc,
- l.toArray(new TypeAnnotation[0]),
- getTypeAnnotations(),
- getDecl());
+ newLoc,
+ l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
+ getTypeAnnotations(),
+ getDecl());
}
return res;
}
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java Wed Jan 06 14:54:24 2016 +0000
@@ -299,7 +299,7 @@
}});
}
- private transient volatile Method[] memberMethods = null;
+ private transient volatile Method[] memberMethods;
/**
* Validates that a method is structurally appropriate for an
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotation.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -187,13 +187,28 @@
return new LocationInfo(newDepth, res);
}
+ /** Pop a series of locations matching {@code tag}. Stop poping as soon as a non-matching tag is found. */
+ public LocationInfo popAllLocations(byte tag) {
+ LocationInfo l = this;
+ int newDepth = l.depth;
+ while(newDepth > 0 && l.locations[newDepth - 1].tag == tag) {
+ newDepth--;
+ }
+ if (newDepth != l.depth) {
+ Location[] res = new Location[newDepth];
+ System.arraycopy(this.locations, 0, res, 0, newDepth);
+ return new LocationInfo(newDepth, res);
+ } else
+ return l;
+ }
+
public TypeAnnotation[] filter(TypeAnnotation[] ta) {
ArrayList<TypeAnnotation> l = new ArrayList<>(ta.length);
for (TypeAnnotation t : ta) {
if (isSameLocationInfo(t.getLocationInfo()))
l.add(t);
}
- return l.toArray(new TypeAnnotation[0]);
+ return l.toArray(AnnotatedTypeFactory.EMPTY_TYPE_ANNOTATION_ARRAY);
}
boolean isSameLocationInfo(LocationInfo other) {
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/TypeAnnotationParser.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -32,7 +32,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import jdk.internal.misc.SharedSecrets;
@@ -67,9 +66,8 @@
Type type,
TypeAnnotationTarget filter) {
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
- cp,
- decl,
- container);
+ cp, decl, container);
+
List<TypeAnnotation> l = new ArrayList<>(tas.length);
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
@@ -78,10 +76,10 @@
}
TypeAnnotation[] typeAnnotations = l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY);
return AnnotatedTypeFactory.buildAnnotatedType(type,
- LocationInfo.BASE_LOCATION,
- typeAnnotations,
- typeAnnotations,
- decl);
+ AnnotatedTypeFactory.nestingForType(type, LocationInfo.BASE_LOCATION),
+ typeAnnotations,
+ typeAnnotations,
+ decl);
}
/**
@@ -110,9 +108,8 @@
ArrayList[] l = new ArrayList[size]; // array of ArrayList<TypeAnnotation>
TypeAnnotation[] tas = parseTypeAnnotations(rawAnnotations,
- cp,
- decl,
- container);
+ cp, decl, container);
+
for (TypeAnnotation t : tas) {
TypeAnnotationTargetInfo ti = t.getTargetInfo();
if (ti.getTarget() == filter) {
@@ -136,10 +133,10 @@
typeAnnotations = EMPTY_TYPE_ANNOTATION_ARRAY;
}
result[i] = AnnotatedTypeFactory.buildAnnotatedType(types[i],
- LocationInfo.BASE_LOCATION,
- typeAnnotations,
- typeAnnotations,
- decl);
+ AnnotatedTypeFactory.nestingForType(types[i], LocationInfo.BASE_LOCATION),
+ typeAnnotations,
+ typeAnnotations,
+ decl);
}
return result;
@@ -278,7 +275,7 @@
}
}
res[i] = AnnotatedTypeFactory.buildAnnotatedType(bounds[i],
- loc,
+ AnnotatedTypeFactory.nestingForType(bounds[i], loc),
l.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
candidates.toArray(EMPTY_TYPE_ANNOTATION_ARRAY),
(AnnotatedElement)decl);
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed Jan 06 14:54:24 2016 +0000
@@ -39,7 +39,7 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS9Attribute.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,7 +38,7 @@
import sun.security.util.DerInputStream;
import sun.security.util.DerOutputStream;
import sun.security.util.ObjectIdentifier;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* Class supporting any PKCS9 attributes.
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SignerInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,7 @@
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import sun.security.x509.KeyUsageExtension;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* A SignerInfo, as defined in PKCS#7's signedData type.
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/pkcs/SigningCertificateInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,7 +28,7 @@
import java.io.IOException;
import java.util.ArrayList;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.DerInputStream;
import sun.security.util.DerValue;
import sun.security.x509.GeneralNames;
--- a/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/provider/SeedGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -75,7 +75,6 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Random;
-import sun.misc.ManagedLocalsThread;
import sun.security.util.Debug;
abstract class SeedGenerator {
@@ -305,9 +304,11 @@
}
finalsg[0] = new ThreadGroup
(group, "SeedGenerator ThreadGroup");
- Thread newT = new ManagedLocalsThread(finalsg[0],
+ Thread newT = new Thread(finalsg[0],
ThreadedSeedGenerator.this,
- "SeedGenerator Thread");
+ "SeedGenerator Thread",
+ 0,
+ false);
newT.setPriority(Thread.MIN_PRIORITY);
newT.setDaemon(true);
return newT;
@@ -342,8 +343,8 @@
// Start some noisy threads
try {
BogusThread bt = new BogusThread();
- Thread t = new ManagedLocalsThread
- (seedGroup, bt, "SeedGenerator Thread");
+ Thread t = new Thread
+ (seedGroup, bt, "SeedGenerator Thread", 0, false);
t.start();
} catch (Exception e) {
throw new InternalError("internal error: " +
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/CertId.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/CertId.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import java.security.cert.X509Certificate;
import java.util.Arrays;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPRequest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPRequest.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import java.util.Collections;
import java.util.List;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
import sun.security.x509.PKIXExtensions;
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/OCSPResponse.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,7 +44,7 @@
import java.util.Set;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.action.GetIntegerAction;
import sun.security.x509.*;
import sun.security.util.*;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherBox.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,7 +42,7 @@
import static sun.security.ssl.CipherSuite.*;
import static sun.security.ssl.CipherSuite.CipherType.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
@@ -1105,41 +1105,6 @@
return fragLen;
}
-
- /*
- * Is this cipher available?
- *
- * This method can only be called by CipherSuite.BulkCipher.isAvailable()
- * to test the availability of a cipher suites. Please DON'T use it in
- * other places, otherwise, the behavior may be unexpected because we may
- * initialize AEAD cipher improperly in the method.
- */
- Boolean isAvailable() {
- // We won't know whether a cipher for a particular key size is
- // available until the cipher is successfully initialized.
- //
- // We do not initialize AEAD cipher in the constructor. Need to
- // initialize the cipher to ensure that the AEAD mode for a
- // particular key size is supported.
- if (cipherType == AEAD_CIPHER) {
- try {
- Authenticator authenticator =
- new Authenticator(protocolVersion);
- byte[] nonce = authenticator.sequenceNumber();
- byte[] iv = Arrays.copyOf(fixedIv,
- fixedIv.length + nonce.length);
- System.arraycopy(nonce, 0, iv, fixedIv.length, nonce.length);
- GCMParameterSpec spec = new GCMParameterSpec(tagSize * 8, iv);
-
- cipher.init(mode, key, spec, random);
- } catch (Exception e) {
- return Boolean.FALSE;
- }
- } // Otherwise, we have initialized the cipher in the constructor.
-
- return Boolean.TRUE;
- }
-
/**
* Sanity check the length of a fragment before decryption.
*
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuite.java Wed Jan 06 14:54:24 2016 +0000
@@ -77,12 +77,6 @@
// minimum priority for default enabled CipherSuites
static final int DEFAULT_SUITES_PRIORITY = 300;
- // Flag indicating if CipherSuite availability can change dynamically.
- // This is the case when we rely on a JCE cipher implementation that
- // may not be available in the installed JCE providers.
- // It is true because we might not have an ECC implementation.
- static final boolean DYNAMIC_AVAILABILITY = true;
-
private static final boolean ALLOW_ECC = Debug.getBooleanProperty
("com.sun.net.ssl.enableECC", true);
@@ -176,9 +170,6 @@
* Return whether this CipherSuite is available for use. A
* CipherSuite may be unavailable even if it is supported
* (i.e. allowed == true) if the required JCE cipher is not installed.
- * In some configuration, this situation may change over time, call
- * CipherSuiteList.clearAvailableCache() before this method to obtain
- * the most current status.
*/
boolean isAvailable() {
return allowed && keyExchange.isAvailable() && cipher.isAvailable();
@@ -471,10 +462,6 @@
B_AES_128_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 16, 12, 4, true),
B_AES_256_GCM(CIPHER_AES_GCM, AEAD_CIPHER, 32, 12, 4, true);
- // Map BulkCipher -> Boolean(available)
- private static final Map<BulkCipher,Boolean> availableCache =
- new HashMap<>(8);
-
// descriptive name including key size, e.g. AES/128
final String description;
@@ -518,6 +505,9 @@
// The secure random used to detect the cipher availability.
private static final SecureRandom secureRandom;
+ // runtime availability
+ private final boolean isAvailable;
+
static {
try {
secureRandom = JsseJce.getSecureRandom();
@@ -542,6 +532,17 @@
this.expandedKeySize = expandedKeySize;
this.exportable = true;
+
+ // availability of this bulk cipher
+ //
+ // Currently all supported ciphers except AES are always available
+ // via the JSSE internal implementations. We also assume AES/128 of
+ // CBC mode is always available since it is shipped with the SunJCE
+ // provider. However, AES/256 is unavailable when the default JCE
+ // policy jurisdiction files are installed because of key length
+ // restrictions.
+ this.isAvailable =
+ allowed ? isUnlimited(keySize, transformation) : false;
}
BulkCipher(String transformation, CipherType cipherType, int keySize,
@@ -558,6 +559,17 @@
this.expandedKeySize = keySize;
this.exportable = false;
+
+ // availability of this bulk cipher
+ //
+ // Currently all supported ciphers except AES are always available
+ // via the JSSE internal implementations. We also assume AES/128 of
+ // CBC mode is always available since it is shipped with the SunJCE
+ // provider. However, AES/256 is unavailable when the default JCE
+ // policy jurisdiction files are installed because of key length
+ // restrictions.
+ this.isAvailable =
+ allowed ? isUnlimited(keySize, transformation) : false;
}
/**
@@ -575,84 +587,27 @@
/**
* Test if this bulk cipher is available. For use by CipherSuite.
- *
- * Currently all supported ciphers except AES are always available
- * via the JSSE internal implementations. We also assume AES/128 of
- * CBC mode is always available since it is shipped with the SunJCE
- * provider. However, AES/256 is unavailable when the default JCE
- * policy jurisdiction files are installed because of key length
- * restrictions, and AEAD is unavailable when the underlying providers
- * do not support AEAD/GCM mode.
*/
boolean isAvailable() {
- if (allowed == false) {
- return false;
- }
-
- if ((this == B_AES_256) ||
- (this.cipherType == CipherType.AEAD_CIPHER)) {
- return isAvailable(this);
- }
-
- // always available
- return true;
- }
-
- // for use by CipherSuiteList.clearAvailableCache();
- static synchronized void clearAvailableCache() {
- if (DYNAMIC_AVAILABILITY) {
- availableCache.clear();
- }
+ return this.isAvailable;
}
- private static synchronized boolean isAvailable(BulkCipher cipher) {
- Boolean b = availableCache.get(cipher);
- if (b == null) {
- int keySizeInBits = cipher.keySize * 8;
- if (keySizeInBits > 128) { // need the JCE unlimited
- // strength jurisdiction policy
- try {
- if (Cipher.getMaxAllowedKeyLength(
- cipher.transformation) < keySizeInBits) {
- b = Boolean.FALSE;
- }
- } catch (Exception e) {
- b = Boolean.FALSE;
- }
- }
+ private static boolean isUnlimited(int keySize, String transformation) {
+ int keySizeInBits = keySize * 8;
+ if (keySizeInBits > 128) { // need the JCE unlimited
+ // strength jurisdiction policy
+ try {
+ if (Cipher.getMaxAllowedKeyLength(
+ transformation) < keySizeInBits) {
- if (b == null) {
- b = Boolean.FALSE; // may be reset to TRUE if
- // the cipher is available
- CipherBox temporary = null;
- try {
- SecretKey key = new SecretKeySpec(
- new byte[cipher.expandedKeySize],
- cipher.algorithm);
- IvParameterSpec iv;
- if (cipher.cipherType == CipherType.AEAD_CIPHER) {
- iv = new IvParameterSpec(
- new byte[cipher.fixedIvSize]);
- } else {
- iv = new IvParameterSpec(new byte[cipher.ivSize]);
- }
- temporary = cipher.newCipher(
- ProtocolVersion.DEFAULT_TLS,
- key, iv, secureRandom, true);
- b = temporary.isAvailable();
- } catch (NoSuchAlgorithmException e) {
- // not available
- } finally {
- if (temporary != null) {
- temporary.dispose();
- }
+ return false;
}
+ } catch (Exception e) {
+ return false;
}
-
- availableCache.put(cipher, b);
}
- return b.booleanValue();
+ return true;
}
@Override
--- a/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/CipherSuiteList.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2012, 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
@@ -74,24 +74,12 @@
throw new IllegalArgumentException("CipherSuites may not be null");
}
cipherSuites = new ArrayList<CipherSuite>(names.length);
- // refresh available cache once if a CipherSuite is not available
- // (maybe new JCE providers have been installed)
- boolean refreshed = false;
for (int i = 0; i < names.length; i++) {
String suiteName = names[i];
CipherSuite suite = CipherSuite.valueOf(suiteName);
if (suite.isAvailable() == false) {
- if (refreshed == false) {
- // clear the cache so that the isAvailable() call below
- // does a full check
- clearAvailableCache();
- refreshed = true;
- }
- // still missing?
- if (suite.isAvailable() == false) {
- throw new IllegalArgumentException("Cannot support "
- + suiteName + " with currently installed providers");
- }
+ throw new IllegalArgumentException("Cannot support "
+ + suiteName + " with currently installed providers");
}
cipherSuites.add(suite);
}
@@ -195,16 +183,4 @@
}
s.putBytes16(suiteBytes);
}
-
- /**
- * Clear cache of available ciphersuites. If we support all ciphers
- * internally, there is no need to clear the cache and calling this
- * method has no effect.
- */
- static synchronized void clearAvailableCache() {
- if (CipherSuite.DYNAMIC_AVAILABILITY) {
- CipherSuite.BulkCipher.clearAvailableCache();
- JsseJce.clearEcAvailable();
- }
- }
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.HandshakeMessage.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.Ciphertext.RecordType;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,7 @@
import java.security.AccessController;
import java.util.Locale;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import java.nio.ByteBuffer;
import sun.security.action.GetPropertyAction;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,7 @@
import javax.crypto.spec.*;
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.internal.spec.*;
import sun.security.internal.interfaces.TlsMasterSecret;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/InputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/InputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/JsseJce.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/JsseJce.java Wed Jan 06 14:54:24 2016 +0000
@@ -55,11 +55,6 @@
private static final ProviderList fipsProviderList;
- // Flag indicating whether EC crypto is available.
- // If null, then we have not checked yet.
- // If yes, then all the EC based crypto we need is available.
- private static Boolean ecAvailable;
-
// Flag indicating whether Kerberos crypto is available.
// If true, then all the Kerberos-based crypto we need is available.
private static final boolean kerberosAvailable;
@@ -180,24 +175,8 @@
// no instantiation of this class
}
- static synchronized boolean isEcAvailable() {
- if (ecAvailable == null) {
- try {
- JsseJce.getSignature(SIGNATURE_ECDSA);
- JsseJce.getSignature(SIGNATURE_RAWECDSA);
- JsseJce.getKeyAgreement("ECDH");
- JsseJce.getKeyFactory("EC");
- JsseJce.getKeyPairGenerator("EC");
- ecAvailable = true;
- } catch (Exception e) {
- ecAvailable = false;
- }
- }
- return ecAvailable;
- }
-
- static synchronized void clearEcAvailable() {
- ecAvailable = null;
+ static boolean isEcAvailable() {
+ return EcAvailability.isAvailable;
}
static boolean isKerberosAvailable() {
@@ -399,4 +378,27 @@
}
}
+
+ // lazy initialization holder class idiom for static default parameters
+ //
+ // See Effective Java Second Edition: Item 71.
+ private static class EcAvailability {
+ // Is EC crypto available?
+ private final static boolean isAvailable;
+
+ static {
+ boolean mediator = true;
+ try {
+ JsseJce.getSignature(SIGNATURE_ECDSA);
+ JsseJce.getSignature(SIGNATURE_RAWECDSA);
+ JsseJce.getKeyAgreement("ECDH");
+ JsseJce.getKeyFactory("EC");
+ JsseJce.getKeyPairGenerator("EC");
+ } catch (Exception e) {
+ mediator = false;
+ }
+
+ isAvailable = mediator;
+ }
+ }
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import java.util.Arrays;
import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -52,18 +52,8 @@
private X509TrustManager trustManager;
private SecureRandom secureRandom;
- // supported and default protocols
- private ProtocolList defaultServerProtocolList;
- private ProtocolList defaultClientProtocolList;
- private ProtocolList supportedProtocolList;
-
- // supported and default cipher suites
- private CipherSuiteList defaultServerCipherSuiteList;
- private CipherSuiteList defaultClientCipherSuiteList;
- private CipherSuiteList supportedCipherSuiteList;
-
// DTLS cookie exchange manager
- private HelloCookieManager helloCookieManager;
+ private volatile HelloCookieManager helloCookieManager;
private StatusResponseManager statusResponseManager;
@@ -117,6 +107,7 @@
if (debug != null && Debug.isOn("sslctx")) {
System.out.println("done seeding SecureRandom");
}
+
isInitialized = true;
}
@@ -242,13 +233,20 @@
return ephemeralKeyManager;
}
+ // Used for DTLS in server mode only, see ServerHandshaker.
HelloCookieManager getHelloCookieManager() {
if (!isInitialized) {
throw new IllegalStateException("SSLContext is not initialized");
}
- if (helloCookieManager == null) {
- helloCookieManager = getHelloCookieManager(secureRandom);
+ if (helloCookieManager != null) {
+ return helloCookieManager;
+ }
+
+ synchronized (this) {
+ if (helloCookieManager == null) {
+ helloCookieManager = getHelloCookieManager(secureRandom);
+ }
}
return helloCookieManager;
@@ -263,78 +261,34 @@
return statusResponseManager;
}
- abstract SSLParameters getDefaultServerSSLParams();
- abstract SSLParameters getDefaultClientSSLParams();
- abstract SSLParameters getSupportedSSLParams();
+ // Get supported ProtocolList.
+ abstract ProtocolList getSuportedProtocolList();
+
+ // Get default ProtocolList for server mode.
+ abstract ProtocolList getServerDefaultProtocolList();
+
+ // Get default ProtocolList for client mode.
+ abstract ProtocolList getClientDefaultProtocolList();
- // Get supported ProtocolList.
- ProtocolList getSuportedProtocolList() {
- if (supportedProtocolList == null) {
- supportedProtocolList =
- new ProtocolList(getSupportedSSLParams().getProtocols());
- }
+ // Get supported CipherSuiteList.
+ abstract CipherSuiteList getSupportedCipherSuiteList();
- return supportedProtocolList;
- }
+ // Get default CipherSuiteList for server mode.
+ abstract CipherSuiteList getServerDefaultCipherSuiteList();
+
+ // Get default CipherSuiteList for client mode.
+ abstract CipherSuiteList getClientDefaultCipherSuiteList();
// Get default ProtocolList.
ProtocolList getDefaultProtocolList(boolean roleIsServer) {
- if (roleIsServer) {
- if (defaultServerProtocolList == null) {
- defaultServerProtocolList = new ProtocolList(
- getDefaultServerSSLParams().getProtocols());
- }
-
- return defaultServerProtocolList;
- } else {
- if (defaultClientProtocolList == null) {
- defaultClientProtocolList = new ProtocolList(
- getDefaultClientSSLParams().getProtocols());
- }
-
- return defaultClientProtocolList;
- }
- }
-
- // Get supported CipherSuiteList.
- CipherSuiteList getSupportedCipherSuiteList() {
- // The maintenance of cipher suites needs to be synchronized.
- synchronized (this) {
- // Clear cache of available ciphersuites.
- clearAvailableCache();
-
- if (supportedCipherSuiteList == null) {
- supportedCipherSuiteList = getApplicableCipherSuiteList(
- getSuportedProtocolList(), false);
- }
-
- return supportedCipherSuiteList;
- }
+ return roleIsServer ? getServerDefaultProtocolList()
+ : getClientDefaultProtocolList();
}
// Get default CipherSuiteList.
CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
- // The maintenance of cipher suites needs to be synchronized.
- synchronized (this) {
- // Clear cache of available ciphersuites.
- clearAvailableCache();
-
- if (roleIsServer) {
- if (defaultServerCipherSuiteList == null) {
- defaultServerCipherSuiteList = getApplicableCipherSuiteList(
- getDefaultProtocolList(true), true);
- }
-
- return defaultServerCipherSuiteList;
- } else {
- if (defaultClientCipherSuiteList == null) {
- defaultClientCipherSuiteList = getApplicableCipherSuiteList(
- getDefaultProtocolList(false), true);
- }
-
- return defaultClientCipherSuiteList;
- }
- }
+ return roleIsServer ? getServerDefaultCipherSuiteList()
+ : getClientDefaultCipherSuiteList();
}
/**
@@ -342,8 +296,8 @@
* protocols. See: SSLSocket/SSLEngine.setEnabledProtocols()
*/
boolean isDefaultProtocolList(ProtocolList protocols) {
- return (protocols == defaultServerProtocolList) ||
- (protocols == defaultClientProtocolList);
+ return (protocols == getServerDefaultProtocolList()) ||
+ (protocols == getClientDefaultProtocolList());
}
/**
@@ -351,8 +305,8 @@
* protocols. See: SSLSocket/SSLEngine.setEnabledProtocols()
*/
boolean isDefaultCipherSuiteList(CipherSuiteList cipherSuites) {
- return (cipherSuites == defaultClientCipherSuiteList) ||
- (cipherSuites == defaultServerCipherSuiteList);
+ return (cipherSuites == getServerDefaultCipherSuiteList()) ||
+ (cipherSuites == getClientDefaultCipherSuiteList());
}
/*
@@ -405,24 +359,6 @@
return new CipherSuiteList(suites);
}
- /**
- * Clear cache of available ciphersuites. If we support all ciphers
- * internally, there is no need to clear the cache and calling this
- * method has no effect.
- *
- * Note that every call to clearAvailableCache() and the maintenance of
- * cipher suites need to be synchronized with this instance.
- */
- private void clearAvailableCache() {
- if (CipherSuite.DYNAMIC_AVAILABILITY) {
- supportedCipherSuiteList = null;
- defaultServerCipherSuiteList = null;
- defaultClientCipherSuiteList = null;
- CipherSuite.BulkCipher.clearAvailableCache();
- JsseJce.clearEcAvailable();
- }
- }
-
private static String[] getAvailableProtocols(
ProtocolVersion[] protocolCandidates) {
@@ -479,31 +415,28 @@
* @see SSLContext
*/
private abstract static class AbstractTLSContext extends SSLContextImpl {
- // parameters
- private static final SSLParameters defaultServerSSLParams;
- private static final SSLParameters supportedSSLParams;
+ private static final ProtocolList supportedProtocolList;
+ private static final ProtocolList serverDefaultProtocolList;
+
+ private static final CipherSuiteList supportedCipherSuiteList;
+ private static final CipherSuiteList serverDefaultCipherSuiteList;
static {
- // supported SSL parameters
- supportedSSLParams = new SSLParameters();
-
- // candidates for available protocols
- ProtocolVersion[] candidates;
-
if (SunJSSE.isFIPS()) {
- supportedSSLParams.setProtocols(new String[] {
+ supportedProtocolList = new ProtocolList(new String[] {
ProtocolVersion.TLS10.name,
ProtocolVersion.TLS11.name,
ProtocolVersion.TLS12.name
});
- candidates = new ProtocolVersion[] {
+ serverDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.TLS10,
ProtocolVersion.TLS11,
ProtocolVersion.TLS12
- };
+ }));
} else {
- supportedSSLParams.setProtocols(new String[] {
+ supportedProtocolList = new ProtocolList(new String[] {
ProtocolVersion.SSL20Hello.name,
ProtocolVersion.SSL30.name,
ProtocolVersion.TLS10.name,
@@ -511,28 +444,40 @@
ProtocolVersion.TLS12.name
});
- candidates = new ProtocolVersion[] {
+ serverDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.SSL20Hello,
ProtocolVersion.SSL30,
ProtocolVersion.TLS10,
ProtocolVersion.TLS11,
ProtocolVersion.TLS12
- };
+ }));
}
- defaultServerSSLParams = new SSLParameters();
- defaultServerSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ supportedCipherSuiteList = getApplicableCipherSuiteList(
+ supportedProtocolList, false); // all supported
+ serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ serverDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultServerSSLParams() {
- return defaultServerSSLParams;
+ ProtocolList getSuportedProtocolList() {
+ return supportedProtocolList;
}
@Override
- SSLParameters getSupportedSSLParams() {
- return supportedSSLParams;
+ CipherSuiteList getSupportedCipherSuiteList() {
+ return supportedCipherSuiteList;
+ }
+
+ @Override
+ ProtocolList getServerDefaultProtocolList() {
+ return serverDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getServerDefaultCipherSuiteList() {
+ return serverDefaultCipherSuiteList;
}
@Override
@@ -552,30 +497,35 @@
* @see SSLContext
*/
public static final class TLS10Context extends AbstractTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
static {
- // candidates for available protocols
- ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.TLS10
- };
+ }));
} else {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.SSL30,
ProtocolVersion.TLS10
- };
+ }));
}
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -585,32 +535,37 @@
* @see SSLContext
*/
public static final class TLS11Context extends AbstractTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
static {
- // candidates for available protocols
- ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.TLS10,
ProtocolVersion.TLS11
- };
+ }));
} else {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.SSL30,
ProtocolVersion.TLS10,
ProtocolVersion.TLS11
- };
+ }));
}
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -620,34 +575,39 @@
* @see SSLContext
*/
public static final class TLS12Context extends AbstractTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
static {
- // candidates for available protocols
- ProtocolVersion[] candidates;
if (SunJSSE.isFIPS()) {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.TLS10,
ProtocolVersion.TLS11,
ProtocolVersion.TLS12
- };
+ }));
} else {
- candidates = new ProtocolVersion[] {
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.SSL30,
ProtocolVersion.TLS10,
ProtocolVersion.TLS11,
ProtocolVersion.TLS12
- };
+ }));
}
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -719,7 +679,9 @@
*/
private static class CustomizedTLSContext extends AbstractTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
+
private static IllegalArgumentException reservedException = null;
// Don't want a java.lang.LinkageError for illegal system property.
@@ -766,11 +728,13 @@
candidates = customizedTLSProtocols.toArray(candidates);
}
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
+ clientDefaultProtocolList = new ProtocolList(
getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
} else {
- defaultClientSSLParams = null; // unlikely to be used
+ clientDefaultProtocolList = null; // unlikely to be used
+ clientDefaultCipherSuiteList = null; // unlikely to be used
}
}
@@ -781,8 +745,13 @@
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -795,71 +764,53 @@
// use the default constructor and methods
}
- /*
- * The SSLContext implementation for default "Default" algorithm
- *
- * @see SSLContext
- */
- public static final class DefaultSSLContext extends CustomizedTLSContext {
+ // lazy initialization holder class idiom for static default parameters
+ //
+ // See Effective Java Second Edition: Item 71.
+ private static final class DefaultManagersHolder {
private static final String NONE = "NONE";
private static final String P11KEYSTORE = "PKCS11";
- private static volatile SSLContextImpl defaultImpl;
+ private static final TrustManager[] trustManagers;
+ private static final KeyManager[] keyManagers;
- private static TrustManager[] defaultTrustManagers;
- private static KeyManager[] defaultKeyManagers;
+ static Exception reservedException = null;
- public DefaultSSLContext() throws Exception {
+ static {
+ TrustManager[] tmMediator;
try {
- super.engineInit(getDefaultKeyManager(),
- getDefaultTrustManager(), null);
+ tmMediator = getTrustManagers();
} catch (Exception e) {
- if (debug != null && Debug.isOn("defaultctx")) {
- System.out.println("default context init failed: " + e);
+ reservedException = e;
+ tmMediator = new TrustManager[0];
+ }
+ trustManagers = tmMediator;
+
+ if (reservedException == null) {
+ KeyManager[] kmMediator;
+ try {
+ kmMediator = getKeyManagers();
+ } catch (Exception e) {
+ reservedException = e;
+ kmMediator = new KeyManager[0];
}
- throw e;
- }
-
- if (defaultImpl == null) {
- defaultImpl = this;
+ keyManagers = kmMediator;
+ } else {
+ keyManagers = new KeyManager[0];
}
}
- @Override
- protected void engineInit(KeyManager[] km, TrustManager[] tm,
- SecureRandom sr) throws KeyManagementException {
- throw new KeyManagementException
- ("Default SSLContext is initialized automatically");
- }
-
- static synchronized SSLContextImpl getDefaultImpl() throws Exception {
- if (defaultImpl == null) {
- new DefaultSSLContext();
- }
- return defaultImpl;
- }
-
- private static synchronized TrustManager[] getDefaultTrustManager()
- throws Exception {
- if (defaultTrustManagers != null) {
- return defaultTrustManagers;
- }
-
+ private static TrustManager[] getTrustManagers() throws Exception {
KeyStore ks =
TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
- defaultTrustManagers = tmf.getTrustManagers();
- return defaultTrustManagers;
+ return tmf.getTrustManagers();
}
- private static synchronized KeyManager[] getDefaultKeyManager()
- throws Exception {
- if (defaultKeyManagers != null) {
- return defaultKeyManagers;
- }
+ private static KeyManager[] getKeyManagers() throws Exception {
final Map<String,String> props = new HashMap<>();
AccessController.doPrivileged(
@@ -956,8 +907,71 @@
kmf.init(ks, passwd);
}
- defaultKeyManagers = kmf.getKeyManagers();
- return defaultKeyManagers;
+ return kmf.getKeyManagers();
+ }
+ }
+
+ // lazy initialization holder class idiom for static default parameters
+ //
+ // See Effective Java Second Edition: Item 71.
+ private static final class DefaultSSLContextHolder {
+
+ private static final SSLContextImpl sslContext;
+ static Exception reservedException = null;
+
+ static {
+ SSLContextImpl mediator = null;
+ if (DefaultManagersHolder.reservedException != null) {
+ reservedException = DefaultManagersHolder.reservedException;
+ } else {
+ try {
+ mediator = new DefaultSSLContext();
+ } catch (Exception e) {
+ reservedException = e;
+ }
+ }
+
+ sslContext = mediator;
+ }
+ }
+
+ /*
+ * The SSLContext implementation for default "Default" algorithm
+ *
+ * @see SSLContext
+ */
+ public static final class DefaultSSLContext extends CustomizedTLSContext {
+
+ // public constructor for SSLContext.getInstance("Default")
+ public DefaultSSLContext() throws Exception {
+ if (DefaultManagersHolder.reservedException != null) {
+ throw DefaultManagersHolder.reservedException;
+ }
+
+ try {
+ super.engineInit(DefaultManagersHolder.keyManagers,
+ DefaultManagersHolder.trustManagers, null);
+ } catch (Exception e) {
+ if (debug != null && Debug.isOn("defaultctx")) {
+ System.out.println("default context init failed: " + e);
+ }
+ throw e;
+ }
+ }
+
+ @Override
+ protected void engineInit(KeyManager[] km, TrustManager[] tm,
+ SecureRandom sr) throws KeyManagementException {
+ throw new KeyManagementException
+ ("Default SSLContext is initialized automatically");
+ }
+
+ static SSLContextImpl getDefaultImpl() throws Exception {
+ if (DefaultSSLContextHolder.reservedException != null) {
+ throw DefaultSSLContextHolder.reservedException;
+ }
+
+ return DefaultSSLContextHolder.sslContext;
}
}
@@ -971,39 +985,50 @@
* @see SSLContext
*/
private abstract static class AbstractDTLSContext extends SSLContextImpl {
- // parameters
- private static final SSLParameters defaultServerSSLParams;
- private static final SSLParameters supportedSSLParams;
+ private static final ProtocolList supportedProtocolList;
+ private static final ProtocolList serverDefaultProtocolList;
+
+ private static final CipherSuiteList supportedCipherSuiteList;
+ private static final CipherSuiteList serverDefaultCipherSuiteList;
static {
- // supported SSL parameters
- supportedSSLParams = new SSLParameters();
-
// Both DTLSv1.0 and DTLSv1.2 can be used in FIPS mode.
- supportedSSLParams.setProtocols(new String[] {
+ supportedProtocolList = new ProtocolList(new String[] {
ProtocolVersion.DTLS10.name,
ProtocolVersion.DTLS12.name
});
- // candidates for available protocols
- ProtocolVersion[] candidates = new ProtocolVersion[] {
+ // available protocols for server mode
+ serverDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.DTLS10,
ProtocolVersion.DTLS12
- };
+ }));
- defaultServerSSLParams = new SSLParameters();
- defaultServerSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ supportedCipherSuiteList = getApplicableCipherSuiteList(
+ supportedProtocolList, false); // all supported
+ serverDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ serverDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultServerSSLParams() {
- return defaultServerSSLParams;
+ ProtocolList getSuportedProtocolList() {
+ return supportedProtocolList;
}
@Override
- SSLParameters getSupportedSSLParams() {
- return supportedSSLParams;
+ CipherSuiteList getSupportedCipherSuiteList() {
+ return supportedCipherSuiteList;
+ }
+
+ @Override
+ ProtocolList getServerDefaultProtocolList() {
+ return serverDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getServerDefaultCipherSuiteList() {
+ return serverDefaultCipherSuiteList;
}
@Override
@@ -1028,22 +1053,28 @@
* @see SSLContext
*/
public static final class DTLS10Context extends AbstractDTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
static {
- // candidates for available protocols
- ProtocolVersion[] candidates = new ProtocolVersion[] {
+ // available protocols for client mode
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.DTLS10
- };
+ }));
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -1053,23 +1084,29 @@
* @see SSLContext
*/
public static final class DTLS12Context extends AbstractDTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
static {
- // candidates for available protocols
- ProtocolVersion[] candidates = new ProtocolVersion[] {
+ // available protocols for client mode
+ clientDefaultProtocolList = new ProtocolList(
+ getAvailableProtocols(new ProtocolVersion[] {
ProtocolVersion.DTLS10,
ProtocolVersion.DTLS12
- };
+ }));
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
- getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
@@ -1079,7 +1116,9 @@
* @see SSLContext
*/
private static class CustomizedDTLSContext extends AbstractDTLSContext {
- private static final SSLParameters defaultClientSSLParams;
+ private static final ProtocolList clientDefaultProtocolList;
+ private static final CipherSuiteList clientDefaultCipherSuiteList;
+
private static IllegalArgumentException reservedException = null;
// Don't want a java.lang.LinkageError for illegal system property.
@@ -1119,11 +1158,13 @@
candidates = customizedDTLSProtocols.toArray(candidates);
}
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(
+ clientDefaultProtocolList = new ProtocolList(
getAvailableProtocols(candidates));
+ clientDefaultCipherSuiteList = getApplicableCipherSuiteList(
+ clientDefaultProtocolList, true); // enabled only
} else {
- defaultClientSSLParams = null; // unlikely to be used
+ clientDefaultProtocolList = null; // unlikely to be used
+ clientDefaultCipherSuiteList = null; // unlikely to be used
}
}
@@ -1134,8 +1175,13 @@
}
@Override
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
+ ProtocolList getClientDefaultProtocolList() {
+ return clientDefaultProtocolList;
+ }
+
+ @Override
+ CipherSuiteList getClientDefaultCipherSuiteList() {
+ return clientDefaultCipherSuiteList;
}
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineInputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineOutputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,7 @@
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import static sun.security.ssl.Ciphertext.RecordType;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -130,7 +130,7 @@
* also since counters make shorter debugging IDs than the big ones
* we use in the protocol for uniqueness-over-time.
*/
- private static volatile int counter = 0;
+ private static volatile int counter;
/*
* Use of session caches is globally enabled/disabled.
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -40,7 +40,6 @@
import javax.crypto.BadPaddingException;
import javax.net.ssl.*;
-import sun.misc.ManagedLocalsThread;
import jdk.internal.misc.JavaNetInetAddressAccess;
import jdk.internal.misc.SharedSecrets;
@@ -1153,10 +1152,13 @@
HandshakeCompletedEvent event =
new HandshakeCompletedEvent(this, sess);
- Thread thread = new ManagedLocalsThread(
+ Thread thread = new Thread(
+ null,
new NotifyHandshake(
handshakeListeners.entrySet(), event),
- "HandshakeCompletedNotify-Thread");
+ "HandshakeCompletedNotify-Thread",
+ 0,
+ false);
thread.start();
}
}
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketInputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSocketOutputRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,7 @@
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SignatureAndHashAlgorithm.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -416,12 +416,18 @@
"SHA1withRSA", --p);
supports(HashAlgorithm.SHA1, SignatureAlgorithm.ECDSA,
"SHA1withECDSA", --p);
+
if (Security.getProvider("SunMSCAPI") == null) {
+ supports(HashAlgorithm.SHA224, SignatureAlgorithm.DSA,
+ "SHA224withDSA", --p);
supports(HashAlgorithm.SHA224, SignatureAlgorithm.RSA,
"SHA224withRSA", --p);
supports(HashAlgorithm.SHA224, SignatureAlgorithm.ECDSA,
"SHA224withECDSA", --p);
}
+
+ supports(HashAlgorithm.SHA256, SignatureAlgorithm.DSA,
+ "SHA256withDSA", --p);
supports(HashAlgorithm.SHA256, SignatureAlgorithm.RSA,
"SHA256withRSA", --p);
supports(HashAlgorithm.SHA256, SignatureAlgorithm.ECDSA,
--- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java Wed Jan 06 14:54:24 2016 +0000
@@ -2956,7 +2956,7 @@
if (v.length == 0) {
out.println(rb.getString(".Empty.value."));
} else {
- new sun.misc.HexDumpEncoder().encodeBuffer(ext.getExtensionValue(), out);
+ new sun.security.util.HexDumpEncoder().encodeBuffer(ext.getExtensionValue(), out);
out.println();
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/HexDumpEncoder.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1995, 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.security.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * This class encodes a buffer into the classic: "Hexadecimal Dump" format of
+ * the past. It is useful for analyzing the contents of binary buffers.
+ * The format produced is as follows:
+ * <pre>
+ * xxxx: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff ................
+ * </pre>
+ * Where xxxx is the offset into the buffer in 16 byte chunks, followed
+ * by ascii coded hexadecimal bytes followed by the ASCII representation of
+ * the bytes or '.' if they are not valid bytes.
+ *
+ * @author Chuck McManis
+ */
+
+public class HexDumpEncoder {
+
+ private int offset;
+ private int thisLineLength;
+ private int currentByte;
+ private byte thisLine[] = new byte[16];
+
+ static void hexDigit(PrintStream p, byte x) {
+ char c;
+
+ c = (char) ((x >> 4) & 0xf);
+ if (c > 9)
+ c = (char) ((c-10) + 'A');
+ else
+ c = (char)(c + '0');
+ p.write(c);
+ c = (char) (x & 0xf);
+ if (c > 9)
+ c = (char)((c-10) + 'A');
+ else
+ c = (char)(c + '0');
+ p.write(c);
+ }
+
+ protected int bytesPerAtom() {
+ return (1);
+ }
+
+ protected int bytesPerLine() {
+ return (16);
+ }
+
+ protected void encodeBufferPrefix(OutputStream o) throws IOException {
+ offset = 0;
+ pStream = new PrintStream(o);
+ }
+
+ protected void encodeLinePrefix(OutputStream o, int len) throws IOException {
+ hexDigit(pStream, (byte)((offset >>> 8) & 0xff));
+ hexDigit(pStream, (byte)(offset & 0xff));
+ pStream.print(": ");
+ currentByte = 0;
+ thisLineLength = len;
+ }
+
+ protected void encodeAtom(OutputStream o, byte buf[], int off, int len) throws IOException {
+ thisLine[currentByte] = buf[off];
+ hexDigit(pStream, buf[off]);
+ pStream.print(" ");
+ currentByte++;
+ if (currentByte == 8)
+ pStream.print(" ");
+ }
+
+ protected void encodeLineSuffix(OutputStream o) throws IOException {
+ if (thisLineLength < 16) {
+ for (int i = thisLineLength; i < 16; i++) {
+ pStream.print(" ");
+ if (i == 7)
+ pStream.print(" ");
+ }
+ }
+ pStream.print(" ");
+ for (int i = 0; i < thisLineLength; i++) {
+ if ((thisLine[i] < ' ') || (thisLine[i] > 'z')) {
+ pStream.print(".");
+ } else {
+ pStream.write(thisLine[i]);
+ }
+ }
+ pStream.println();
+ offset += thisLineLength;
+ }
+
+ /** Stream that understands "printing" */
+ protected PrintStream pStream;
+
+ /**
+ * This method works around the bizarre semantics of BufferedInputStream's
+ * read method.
+ */
+ protected int readFully(InputStream in, byte buffer[])
+ throws java.io.IOException {
+ for (int i = 0; i < buffer.length; i++) {
+ int q = in.read();
+ if (q == -1)
+ return i;
+ buffer[i] = (byte)q;
+ }
+ return buffer.length;
+ }
+
+ /**
+ * Encode bytes from the input stream, and write them as text characters
+ * to the output stream. This method will run until it exhausts the
+ * input stream, but does not print the line suffix for a final
+ * line that is shorter than bytesPerLine().
+ */
+ public void encode(InputStream inStream, OutputStream outStream)
+ throws IOException
+ {
+ int j;
+ int numBytes;
+ byte tmpbuffer[] = new byte[bytesPerLine()];
+
+ encodeBufferPrefix(outStream);
+
+ while (true) {
+ numBytes = readFully(inStream, tmpbuffer);
+ if (numBytes == 0) {
+ break;
+ }
+ encodeLinePrefix(outStream, numBytes);
+ for (j = 0; j < numBytes; j += bytesPerAtom()) {
+
+ if ((j + bytesPerAtom()) <= numBytes) {
+ encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
+ } else {
+ encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
+ }
+ }
+ if (numBytes < bytesPerLine()) {
+ break;
+ } else {
+ encodeLineSuffix(outStream);
+ }
+ }
+ }
+
+ /**
+ * A 'streamless' version of encode that simply takes a buffer of
+ * bytes and returns a string containing the encoded buffer.
+ */
+ public String encode(byte aBuffer[]) {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
+ String retVal = null;
+ try {
+ encode(inStream, outStream);
+ // explicit ascii->unicode conversion
+ retVal = outStream.toString("ISO-8859-1");
+ } catch (Exception IOException) {
+ // This should never happen.
+ throw new Error("CharacterEncoder.encode internal error");
+ }
+ return (retVal);
+ }
+
+ /**
+ * Return a byte array from the remaining bytes in this ByteBuffer.
+ * <P>
+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+ * <P>
+ * To avoid an extra copy, the implementation will attempt to return the
+ * byte array backing the ByteBuffer. If this is not possible, a
+ * new byte array will be created.
+ */
+ private byte [] getBytes(ByteBuffer bb) {
+ /*
+ * This should never return a BufferOverflowException, as we're
+ * careful to allocate just the right amount.
+ */
+ byte [] buf = null;
+
+ /*
+ * If it has a usable backing byte buffer, use it. Use only
+ * if the array exactly represents the current ByteBuffer.
+ */
+ if (bb.hasArray()) {
+ byte [] tmp = bb.array();
+ if ((tmp.length == bb.capacity()) &&
+ (tmp.length == bb.remaining())) {
+ buf = tmp;
+ bb.position(bb.limit());
+ }
+ }
+
+ if (buf == null) {
+ /*
+ * This class doesn't have a concept of encode(buf, len, off),
+ * so if we have a partial buffer, we must reallocate
+ * space.
+ */
+ buf = new byte[bb.remaining()];
+
+ /*
+ * position() automatically updated
+ */
+ bb.get(buf);
+ }
+
+ return buf;
+ }
+
+ /**
+ * A 'streamless' version of encode that simply takes a ByteBuffer
+ * and returns a string containing the encoded buffer.
+ * <P>
+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+ */
+ public String encode(ByteBuffer aBuffer) {
+ byte [] buf = getBytes(aBuffer);
+ return encode(buf);
+ }
+
+ /**
+ * Encode bytes from the input stream, and write them as text characters
+ * to the output stream. This method will run until it exhausts the
+ * input stream. It differs from encode in that it will add the
+ * line at the end of a final line that is shorter than bytesPerLine().
+ */
+ public void encodeBuffer(InputStream inStream, OutputStream outStream)
+ throws IOException
+ {
+ int j;
+ int numBytes;
+ byte tmpbuffer[] = new byte[bytesPerLine()];
+
+ encodeBufferPrefix(outStream);
+
+ while (true) {
+ numBytes = readFully(inStream, tmpbuffer);
+ if (numBytes == 0) {
+ break;
+ }
+ encodeLinePrefix(outStream, numBytes);
+ for (j = 0; j < numBytes; j += bytesPerAtom()) {
+ if ((j + bytesPerAtom()) <= numBytes) {
+ encodeAtom(outStream, tmpbuffer, j, bytesPerAtom());
+ } else {
+ encodeAtom(outStream, tmpbuffer, j, (numBytes)- j);
+ }
+ }
+ encodeLineSuffix(outStream);
+ if (numBytes < bytesPerLine()) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * Encode the buffer in <i>aBuffer</i> and write the encoded
+ * result to the OutputStream <i>aStream</i>.
+ */
+ public void encodeBuffer(byte aBuffer[], OutputStream aStream)
+ throws IOException
+ {
+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
+ encodeBuffer(inStream, aStream);
+ }
+
+ /**
+ * A 'streamless' version of encode that simply takes a buffer of
+ * bytes and returns a string containing the encoded buffer.
+ */
+ public String encodeBuffer(byte aBuffer[]) {
+ ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ ByteArrayInputStream inStream = new ByteArrayInputStream(aBuffer);
+ try {
+ encodeBuffer(inStream, outStream);
+ } catch (Exception IOException) {
+ // This should never happen.
+ throw new Error("CharacterEncoder.encodeBuffer internal error");
+ }
+ return (outStream.toString());
+ }
+
+ /**
+ * Encode the <i>aBuffer</i> ByteBuffer and write the encoded
+ * result to the OutputStream <i>aStream</i>.
+ * <P>
+ * The ByteBuffer's position will be advanced to ByteBuffer's limit.
+ */
+ public void encodeBuffer(ByteBuffer aBuffer, OutputStream aStream)
+ throws IOException
+ {
+ byte [] buf = getBytes(aBuffer);
+ encodeBuffer(buf, aStream);
+ }
+
+}
--- a/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/util/SignatureFileVerifier.java Wed Jan 06 14:54:24 2016 +0000
@@ -443,7 +443,7 @@
if (sfAttr != null) {
- //sun.misc.HexDumpEncoder hex = new sun.misc.HexDumpEncoder();
+ //sun.security.util.HexDumpEncoder hex = new sun.security.util.HexDumpEncoder();
//hex.encodeBuffer(data, System.out);
// go through all the attributes and process *-Digest entries
--- a/jdk/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/CertificateExtensions.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import java.security.cert.CertificateException;
import java.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
@@ -376,6 +376,6 @@
@Override public String toString() {
return super.toString() +
"Unparseable " + name + "extension due to\n" + why + "\n\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(getExtensionValue());
+ new HexDumpEncoder().encodeBuffer(getExtensionValue());
}
}
--- a/jdk/src/java.base/share/classes/sun/security/x509/IPAddressName.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/IPAddressName.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,7 @@
import java.lang.Integer;
import java.net.InetAddress;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.BitArray;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
--- a/jdk/src/java.base/share/classes/sun/security/x509/KeyIdentifier.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/KeyIdentifier.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/UniqueIdentity.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/UniqueIdentity.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,7 +27,7 @@
import java.io.IOException;
import java.math.BigInteger;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLEntryImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -35,7 +35,7 @@
import javax.security.auth.x500.X500Principal;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* <p>Abstract class for a revoked certificate in a CRL.
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CRLImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -49,7 +49,7 @@
import sun.security.provider.X509Factory;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* <p>
@@ -1290,7 +1290,7 @@
implements Comparable<X509IssuerSerial> {
final X500Principal issuer;
final BigInteger serial;
- volatile int hashcode = 0;
+ volatile int hashcode;
/**
* Create an X509IssuerSerial.
@@ -1358,13 +1358,16 @@
* @return the hash code value
*/
public int hashCode() {
- if (hashcode == 0) {
- int result = 17;
- result = 37*result + issuer.hashCode();
- result = 37*result + serial.hashCode();
- hashcode = result;
+ int h = hashcode;
+ if (h == 0) {
+ h = 17;
+ h = 37*h + issuer.hashCode();
+ h = 37*h + serial.hashCode();
+ if (h != 0) {
+ hashcode = h;
+ }
}
- return hashcode;
+ return h;
}
@Override
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,7 @@
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import java.util.Base64;
import sun.security.util.*;
import sun.security.provider.X509Factory;
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
import java.util.*;
import sun.security.util.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509Key.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,7 +38,7 @@
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.util.*;
/**
--- a/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/util/calendar/CalendarSystem.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,13 +25,6 @@
package sun.util.calendar;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Properties;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -76,7 +69,7 @@
/////////////////////// Calendar Factory Methods /////////////////////////
- private static volatile boolean initialized = false;
+ private static volatile boolean initialized;
// Map of calendar names and calendar class names
private static ConcurrentMap<String, String> names;
--- a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java Wed Jan 06 14:54:24 2016 +0000
@@ -46,7 +46,7 @@
private final String region;
private final String variant;
- private volatile int hash = 0;
+ private volatile int hash;
// This method must be called only when creating the Locale.* constants.
private BaseLocale(String language, String region) {
@@ -147,7 +147,9 @@
h = 31 * h + script.hashCode();
h = 31 * h + region.hashCode();
h = 31 * h + variant.hashCode();
- hash = h;
+ if (h != 0) {
+ hash = h;
+ }
}
return h;
}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Wed Jan 06 14:54:24 2016 +0000
@@ -114,20 +114,20 @@
}
}
- private volatile BreakIteratorProvider breakIteratorProvider = null;
- private volatile CollatorProvider collatorProvider = null;
- private volatile DateFormatProvider dateFormatProvider = null;
- private volatile DateFormatSymbolsProvider dateFormatSymbolsProvider = null;
- private volatile DecimalFormatSymbolsProvider decimalFormatSymbolsProvider = null;
- private volatile NumberFormatProvider numberFormatProvider = null;
+ private volatile BreakIteratorProvider breakIteratorProvider;
+ private volatile CollatorProvider collatorProvider;
+ private volatile DateFormatProvider dateFormatProvider;
+ private volatile DateFormatSymbolsProvider dateFormatSymbolsProvider;
+ private volatile DecimalFormatSymbolsProvider decimalFormatSymbolsProvider;
+ private volatile NumberFormatProvider numberFormatProvider;
- private volatile CurrencyNameProvider currencyNameProvider = null;
- private volatile LocaleNameProvider localeNameProvider = null;
- private volatile TimeZoneNameProvider timeZoneNameProvider = null;
- private volatile CalendarDataProvider calendarDataProvider = null;
- private volatile CalendarNameProvider calendarNameProvider = null;
+ private volatile CurrencyNameProvider currencyNameProvider;
+ private volatile LocaleNameProvider localeNameProvider;
+ private volatile TimeZoneNameProvider timeZoneNameProvider;
+ private volatile CalendarDataProvider calendarDataProvider;
+ private volatile CalendarNameProvider calendarNameProvider;
- private volatile CalendarProvider calendarProvider = null;
+ private volatile CalendarProvider calendarProvider;
/*
* Getter methods for java.text.spi.* providers
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java Wed Jan 06 14:54:24 2016 +0000
@@ -107,7 +107,7 @@
* Default fallback adapter type, which should return something meaningful in any case.
* This is either CLDR or FALLBACK.
*/
- static volatile LocaleProviderAdapter.Type defaultLocaleProviderAdapter = null;
+ static volatile LocaleProviderAdapter.Type defaultLocaleProviderAdapter;
/**
* Adapter lookup cache.
--- a/jdk/src/java.base/share/classes/sun/util/resources/OpenListResourceBundle.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/classes/sun/util/resources/OpenListResourceBundle.java Wed Jan 06 14:54:24 2016 +0000
@@ -164,6 +164,6 @@
return new HashSet<>();
}
- private volatile Map<String, Object> lookup = null;
+ private volatile Map<String, Object> lookup;
private volatile Set<String> keyset;
}
--- a/jdk/src/java.base/share/conf/security/java.policy Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/share/conf/security/java.policy Wed Jan 06 14:54:24 2016 +0000
@@ -19,6 +19,10 @@
permission java.security.AllPermission;
};
+grant codeBase "jrt:/jdk.dynalink" {
+ permission java.security.AllPermission;
+};
+
grant codeBase "jrt:/jdk.scripting.nashorn" {
permission java.security.AllPermission;
};
--- a/jdk/src/java.base/share/native/libzip/ZipFile.c Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * Copyright (c) 1998, 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.
- */
-
-/*
- * Native method support for java.util.zip.ZipFile
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <ctype.h>
-#include <assert.h>
-#include "jlong.h"
-#include "jvm.h"
-#include "jni.h"
-#include "jni_util.h"
-#include "zip_util.h"
-#ifdef WIN32
-#include "io_util_md.h"
-#else
-#include "io_util.h"
-#endif
-
-#include "java_util_zip_ZipFile.h"
-#include "java_util_jar_JarFile.h"
-
-#define DEFLATED 8
-#define STORED 0
-
-static jfieldID jzfileID;
-
-static int OPEN_READ = java_util_zip_ZipFile_OPEN_READ;
-static int OPEN_DELETE = java_util_zip_ZipFile_OPEN_DELETE;
-
-
-/*
- * Declare library specific JNI_Onload entry if static build
- */
-DEF_STATIC_JNI_OnLoad
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_initIDs(JNIEnv *env, jclass cls)
-{
- jzfileID = (*env)->GetFieldID(env, cls, "jzfile", "J");
- assert(jzfileID != 0);
-}
-
-static void
-ThrowZipException(JNIEnv *env, const char *msg)
-{
- jstring s = NULL;
- jobject x;
-
- if (msg != NULL) {
- s = JNU_NewStringPlatform(env, msg);
- }
- if (s != NULL) {
- x = JNU_NewObjectByName(env,
- "java/util/zip/ZipException",
- "(Ljava/lang/String;)V", s);
- if (x != NULL) {
- (*env)->Throw(env, x);
- }
- }
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_open(JNIEnv *env, jclass cls, jstring name,
- jint mode, jlong lastModified,
- jboolean usemmap)
-{
- const char *path = JNU_GetStringPlatformChars(env, name, 0);
- char *msg = 0;
- jlong result = 0;
- int flag = 0;
- jzfile *zip = 0;
-
- if (mode & OPEN_READ) flag |= O_RDONLY;
-
- if (path != 0) {
- zip = ZIP_Get_From_Cache(path, &msg, lastModified);
- if (zip == 0 && msg == 0) {
- ZFILE zfd = 0;
-#ifdef WIN32
- if (mode & OPEN_DELETE) flag |= O_TEMPORARY;
- zfd = winFileHandleOpen(env, name, flag);
- if (zfd == -1) {
- /* Exception already pending. */
- goto finally;
- }
-#else
- zfd = open(path, flag, 0);
- if (zfd < 0) {
- throwFileNotFoundException(env, name);
- goto finally;
- }
- if (mode & OPEN_DELETE) {
- unlink(path);
- }
-#endif
- zip = ZIP_Put_In_Cache0(path, zfd, &msg, lastModified, usemmap);
- }
-
- if (zip != 0) {
- result = ptr_to_jlong(zip);
- } else if (msg != 0) {
- ThrowZipException(env, msg);
- free(msg);
- } else if (errno == ENOMEM) {
- JNU_ThrowOutOfMemoryError(env, 0);
- } else {
- ThrowZipException(env, "error in opening zip file");
- }
-finally:
- JNU_ReleaseStringPlatformChars(env, name, path);
- }
- return result;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getTotal(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
-
- return zip->total;
-}
-
-JNIEXPORT jboolean JNICALL
-Java_java_util_zip_ZipFile_startsWithLOC(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
-
- return zip->locsig;
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
-{
- ZIP_Close(jlong_to_ptr(zfile));
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
- jbyteArray name, jboolean addSlash)
-{
-#define MAXNAME 1024
- jzfile *zip = jlong_to_ptr(zfile);
- jsize ulen = (*env)->GetArrayLength(env, name);
- char buf[MAXNAME+2], *path;
- jzentry *ze;
-
- if (ulen > MAXNAME) {
- path = malloc(ulen + 2);
- if (path == 0) {
- JNU_ThrowOutOfMemoryError(env, 0);
- return 0;
- }
- } else {
- path = buf;
- }
- (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
- path[ulen] = '\0';
- ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash);
- if (path != buf) {
- free(path);
- }
- return ptr_to_jlong(ze);
-}
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_ZipFile_freeEntry(JNIEnv *env, jclass cls, jlong zfile,
- jlong zentry)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- jzentry *ze = jlong_to_ptr(zentry);
- ZIP_FreeEntry(zip, ze);
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
- jint n)
-{
- jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
- return ptr_to_jlong(ze);
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->csize != 0 ? DEFLATED : STORED;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->flag;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->csize != 0 ? ze->csize : ze->size;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return ze->size;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return (jlong)ze->time & 0xffffffffUL;
-}
-
-JNIEXPORT jlong JNICALL
-Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- return (jlong)ze->crc & 0xffffffffUL;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_java_util_zip_ZipFile_getCommentBytes(JNIEnv *env,
- jclass cls,
- jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- jbyteArray jba = NULL;
-
- if (zip->comment != NULL) {
- if ((jba = (*env)->NewByteArray(env, zip->clen)) == NULL)
- return NULL;
- (*env)->SetByteArrayRegion(env, jba, 0, zip->clen, (jbyte*)zip->comment);
- }
- return jba;
-}
-
-JNIEXPORT jbyteArray JNICALL
-Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env,
- jclass cls,
- jlong zentry, jint type)
-{
- jzentry *ze = jlong_to_ptr(zentry);
- int len = 0;
- jbyteArray jba = NULL;
- switch (type) {
- case java_util_zip_ZipFile_JZENTRY_NAME:
- if (ze->name != 0) {
- len = (int)ze->nlen;
- // Unlike for extra and comment, we never return null for
- // an (extremely rarely seen) empty name
- if ((jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
- }
- break;
- case java_util_zip_ZipFile_JZENTRY_EXTRA:
- if (ze->extra != 0) {
- unsigned char *bp = (unsigned char *)&ze->extra[0];
- len = (bp[0] | (bp[1] << 8));
- if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
- }
- break;
- case java_util_zip_ZipFile_JZENTRY_COMMENT:
- if (ze->comment != 0) {
- len = (int)strlen(ze->comment);
- if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
- break;
- (*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
- }
- break;
- }
- return jba;
-}
-
-JNIEXPORT jint JNICALL
-Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
- jlong zentry, jlong pos, jbyteArray bytes,
- jint off, jint len)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- char *msg;
-
-#define BUFSIZE 8192
- /* copy via tmp stack buffer: */
- jbyte buf[BUFSIZE];
-
- if (len > BUFSIZE) {
- len = BUFSIZE;
- }
-
- ZIP_Lock(zip);
- len = ZIP_Read(zip, jlong_to_ptr(zentry), pos, buf, len);
- msg = zip->msg;
- ZIP_Unlock(zip);
- if (len != -1) {
- (*env)->SetByteArrayRegion(env, bytes, off, len, buf);
- }
-
- if (len == -1) {
- if (msg != 0) {
- ThrowZipException(env, msg);
- } else {
- char errmsg[128];
- sprintf(errmsg, "errno: %d, error: %s\n",
- errno, "Error reading ZIP file");
- JNU_ThrowIOExceptionWithLastError(env, errmsg);
- }
- }
-
- return len;
-}
-
-/*
- * Returns an array of strings representing the names of all entries
- * that begin with "META-INF/" (case ignored). This native method is
- * used in JarFile as an optimization when looking up manifest and
- * signature file entries. Returns null if no entries were found.
- */
-JNIEXPORT jobjectArray JNICALL
-Java_java_util_jar_JarFile_getMetaInfEntryNames(JNIEnv *env, jobject obj)
-{
- jlong zfile = (*env)->GetLongField(env, obj, jzfileID);
- jzfile *zip;
- int i, count;
- jobjectArray result = 0;
-
- if (zfile == 0) {
- JNU_ThrowByName(env,
- "java/lang/IllegalStateException", "zip file closed");
- return NULL;
- }
- zip = jlong_to_ptr(zfile);
-
- /* count the number of valid ZIP metanames */
- count = 0;
- if (zip->metanames != 0) {
- for (i = 0; i < zip->metacount; i++) {
- if (zip->metanames[i] != 0) {
- count++;
- }
- }
- }
-
- /* If some names were found then build array of java strings */
- if (count > 0) {
- jclass cls = JNU_ClassString(env);
- CHECK_NULL_RETURN(cls, NULL);
- result = (*env)->NewObjectArray(env, count, cls, 0);
- CHECK_NULL_RETURN(result, NULL);
- if (result != 0) {
- for (i = 0; i < count; i++) {
- jstring str = (*env)->NewStringUTF(env, zip->metanames[i]);
- if (str == 0) {
- break;
- }
- (*env)->SetObjectArrayElement(env, result, i, str);
- (*env)->DeleteLocalRef(env, str);
- }
- }
- }
- return result;
-}
-
-JNIEXPORT jstring JNICALL
-Java_java_util_zip_ZipFile_getZipMessage(JNIEnv *env, jclass cls, jlong zfile)
-{
- jzfile *zip = jlong_to_ptr(zfile);
- char *msg = zip->msg;
- if (msg == NULL) {
- return NULL;
- }
- return JNU_NewStringPlatform(env, msg);
-}
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -47,7 +47,7 @@
int fdVal;
// ID of native thread doing write, for signalling
- private volatile long thread = 0;
+ private volatile long thread;
// Lock held by current reading thread
private final Object lock = new Object();
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -47,7 +47,7 @@
int fdVal;
// ID of native thread doing read, for signalling
- private volatile long thread = 0;
+ private volatile long thread;
// Lock held by current reading thread
private final Object lock = new Object();
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/MimeTypesFileTypeDetector.java Wed Jan 06 14:54:24 2016 +0000
@@ -52,7 +52,7 @@
private Map<String,String> mimeTypeMap;
// set to true when file loaded
- private volatile boolean loaded = false;
+ private volatile boolean loaded;
public MimeTypesFileTypeDetector(Path filePath) {
mimeTypesFile = filePath;
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixFileSystemProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -69,15 +69,16 @@
private void checkUri(URI uri) {
if (!uri.getScheme().equalsIgnoreCase(getScheme()))
throw new IllegalArgumentException("URI does not match this provider");
- if (uri.getAuthority() != null)
+ if (uri.getRawAuthority() != null)
throw new IllegalArgumentException("Authority component present");
- if (uri.getPath() == null)
+ String path = uri.getPath();
+ if (path == null)
throw new IllegalArgumentException("Path component is undefined");
- if (!uri.getPath().equals("/"))
+ if (!path.equals("/"))
throw new IllegalArgumentException("Path component should be '/'");
- if (uri.getQuery() != null)
+ if (uri.getRawQuery() != null)
throw new IllegalArgumentException("Query component present");
- if (uri.getFragment() != null)
+ if (uri.getRawFragment() != null)
throw new IllegalArgumentException("Fragment component present");
}
--- a/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/unix/classes/sun/nio/fs/UnixUriUtils.java Wed Jan 06 14:54:24 2016 +0000
@@ -49,11 +49,11 @@
String scheme = uri.getScheme();
if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
throw new IllegalArgumentException("URI scheme is not \"file\"");
- if (uri.getAuthority() != null)
+ if (uri.getRawAuthority() != null)
throw new IllegalArgumentException("URI has an authority component");
- if (uri.getFragment() != null)
+ if (uri.getRawFragment() != null)
throw new IllegalArgumentException("URI has a fragment component");
- if (uri.getQuery() != null)
+ if (uri.getRawQuery() != null)
throw new IllegalArgumentException("URI has a query component");
// compatibility with java.io.File
--- a/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -40,7 +40,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
-import sun.misc.ManagedLocalsThread;
/**
* A multi-threaded implementation of Selector for Windows.
@@ -120,7 +119,7 @@
// Lock for interrupt triggering and clearing
private final Object interruptLock = new Object();
- private volatile boolean interruptTriggered = false;
+ private volatile boolean interruptTriggered;
WindowsSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
@@ -404,13 +403,14 @@
}
// Represents a helper thread used for select.
- private final class SelectThread extends ManagedLocalsThread {
+ private final class SelectThread extends Thread {
private final int index; // index of this thread
final SubSelector subSelector;
private long lastRun = 0; // last run number
private volatile boolean zombie;
// Creates a new thread
private SelectThread(int i) {
+ super(null, null, "SelectorHelper", 0, false);
this.index = i;
this.subSelector = new SubSelector(i);
//make sure we wait for next round of poll
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -61,15 +61,16 @@
private void checkUri(URI uri) {
if (!uri.getScheme().equalsIgnoreCase(getScheme()))
throw new IllegalArgumentException("URI does not match this provider");
- if (uri.getAuthority() != null)
+ if (uri.getRawAuthority() != null)
throw new IllegalArgumentException("Authority component present");
- if (uri.getPath() == null)
+ String path = uri.getPath();
+ if (path == null)
throw new IllegalArgumentException("Path component is undefined");
- if (!uri.getPath().equals("/"))
+ if (!path.equals("/"))
throw new IllegalArgumentException("Path component should be '/'");
- if (uri.getQuery() != null)
+ if (uri.getRawQuery() != null)
throw new IllegalArgumentException("Query component present");
- if (uri.getFragment() != null)
+ if (uri.getRawFragment() != null)
throw new IllegalArgumentException("Fragment component present");
}
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsUriSupport.java Wed Jan 06 14:54:24 2016 +0000
@@ -123,16 +123,16 @@
String scheme = uri.getScheme();
if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
throw new IllegalArgumentException("URI scheme is not \"file\"");
- if (uri.getFragment() != null)
+ if (uri.getRawFragment() != null)
throw new IllegalArgumentException("URI has a fragment component");
- if (uri.getQuery() != null)
+ if (uri.getRawQuery() != null)
throw new IllegalArgumentException("URI has a query component");
String path = uri.getPath();
if (path.equals(""))
throw new IllegalArgumentException("URI path component is empty");
// UNC
- String auth = uri.getAuthority();
+ String auth = uri.getRawAuthority();
if (auth != null && !auth.equals("")) {
String host = uri.getHost();
if (host == null)
--- a/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.datatransfer/share/classes/java/awt/datatransfer/DataFlavor.java Wed Jan 06 14:54:24 2016 +0000
@@ -289,6 +289,8 @@
* representationClass = String
* mimeType = "text/html"
* </pre>
+ *
+ * @since 1.8
*/
public static DataFlavor selectionHtmlFlavor = initHtmlDataFlavor("selection");
@@ -301,6 +303,8 @@
* representationClass = String
* mimeType = "text/html"
* </pre>
+ *
+ * @since 1.8
*/
public static DataFlavor fragmentHtmlFlavor = initHtmlDataFlavor("fragment");
@@ -314,6 +318,8 @@
* representationClass = String
* mimeType = "text/html"
* </pre>
+ *
+ * @since 1.8
*/
public static DataFlavor allHtmlFlavor = initHtmlDataFlavor("all");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CMenuItem.m Wed Jan 06 14:54:24 2016 +0000
@@ -24,6 +24,7 @@
*/
#import <JavaNativeFoundation/JavaNativeFoundation.h>
+#include <Carbon/Carbon.h>
#import "CMenuItem.h"
#import "CMenu.h"
@@ -40,7 +41,7 @@
@implementation CMenuItem
- (id) initWithPeer:(jobject)peer asSeparator: (NSNumber *) asSeparator{
-AWT_ASSERT_APPKIT_THREAD;
+ AWT_ASSERT_APPKIT_THREAD;
self = [super initWithPeer:peer];
if (self) {
if ([asSeparator boolValue]) {
@@ -63,13 +64,48 @@
- (BOOL) worksWhenModal {
return YES;
}
+// This is a method written using Carbon framework methods to remove
+// All modifiers including "Shift" modifier.
+// Example 1: Shortcut set is "Command Shift m" returns "m"
+// Example 2: Shortcut set is "Command m" returns "m"
+// Example 3: Shortcut set is "Alt Shift ," returns ","
+
+CFStringRef createStringForKey(CGKeyCode keyCode)
+{
+ TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
+// currentKeyboard now contains the current input source
+ CFDataRef layoutData =
+ TISGetInputSourceProperty(currentKeyboard,
+ kTISPropertyUnicodeKeyLayoutData);
+// the UNICODE keyLayout is fetched from currentKeyboard in layoutData
+ const UCKeyboardLayout *keyboardLayout =
+ (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+// A read-only data pointer is fetched from layoutData
+ UInt32 keysDown = 0;
+ UniChar chars[4];
+ UniCharCount realLength;
+
+ UCKeyTranslate(keyboardLayout,
+ keyCode,
+ kUCKeyActionDisplay,
+ 0,
+ LMGetKbdType(),
+ kUCKeyTranslateNoDeadKeysBit,
+ &keysDown,
+ sizeof(chars) / sizeof(chars[0]),
+ &realLength,
+ chars);
+ CFRelease(currentKeyboard);
+// Converts keyCode, modifier and dead-key state into UNICODE characters
+ return CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1);
+}
// Events
- (void)handleAction:(NSMenuItem *)sender {
-AWT_ASSERT_APPKIT_THREAD;
+ AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
-JNF_COCOA_ENTER(env);
-
+ JNF_COCOA_ENTER(env);
+
// If we are called as a result of user pressing a shortcut, do nothing,
// because AVTView has already sent corresponding key event to the Java
// layer from performKeyEquivalent.
@@ -82,31 +118,37 @@
NSEvent *currEvent = [[NSApplication sharedApplication] currentEvent];
if ([currEvent type] == NSKeyDown) {
NSString *menuKey = [sender keyEquivalent];
- NSString *eventKey = [currEvent charactersIgnoringModifiers];
-
- // Apple uses characters from private Unicode range for some of the
- // keys, so we need to do the same translation here that we do
- // for the regular key down events
- if ([eventKey length] == 1) {
- unichar origChar = [eventKey characterAtIndex:0];
- unichar newChar = NsCharToJavaChar(origChar, 0);
- if (newChar == java_awt_event_KeyEvent_CHAR_UNDEFINED) {
- newChar = origChar;
- }
-
- eventKey = [NSString stringWithCharacters: &newChar length: 1];
- }
-
+// If shortcut is "Command Shift ," the menuKey gets the value ","
+// But [currEvent charactersIgnoringModifiers]; returns "<" and not ","
+// because the charactersIgnoreingModifiers does not ignore "Shift"
+// So a shortcut like "Command Shift m" will return "M" where as the
+// MenuKey will have the value "m". To remove this issue the below
+// createStringForKey is used.
+ NSString *eventKey = createStringForKey([currEvent keyCode]);
+
+// Apple uses characters from private Unicode range for some of the
+// keys, so we need to do the same translation here that we do
+// for the regular key down events
+ if ([eventKey length] == 1) {
+ unichar origChar = [eventKey characterAtIndex:0];
+ unichar newChar = NsCharToJavaChar(origChar, 0);
+ if (newChar == java_awt_event_KeyEvent_CHAR_UNDEFINED) {
+ newChar = origChar;
+ }
+
+ eventKey = [NSString stringWithCharacters: &newChar length: 1];
+ }
+
NSWindow *keyWindow = [NSApp keyWindow];
if ([menuKey isEqualToString:eventKey] && keyWindow != nil) {
return;
}
}
-
+
if (fIsCheckbox) {
static JNF_CLASS_CACHE(jc_CCheckboxMenuItem, "sun/lwawt/macosx/CCheckboxMenuItem");
static JNF_MEMBER_CACHE(jm_ckHandleAction, jc_CCheckboxMenuItem, "handleAction", "(Z)V");
-
+
// Send the opposite of what's currently checked -- the action
// indicates what state we're going to.
NSInteger state = [sender state];
@@ -115,26 +157,26 @@
} else {
static JNF_CLASS_CACHE(jc_CMenuItem, "sun/lwawt/macosx/CMenuItem");
static JNF_MEMBER_CACHE(jm_handleAction, jc_CMenuItem, "handleAction", "(JI)V"); // AWT_THREADING Safe (event)
-
+
NSUInteger modifiers = [currEvent modifierFlags];
jint javaModifiers = NsKeyModifiersToJavaModifiers(modifiers, NO);
-
+
JNFCallVoidMethod(env, fPeer, jm_handleAction, UTC(currEvent), javaModifiers); // AWT_THREADING Safe (event)
}
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
- (void) setJavaLabel:(NSString *)theLabel shortcut:(NSString *)theKeyEquivalent modifierMask:(jint)modifiers {
-
+
NSUInteger modifierMask = 0;
-
+
if (![theKeyEquivalent isEqualToString:@""]) {
// Force the key equivalent to lower case if not using the shift key.
// Otherwise AppKit will draw a Shift glyph in the menu.
if ((modifiers & java_awt_event_KeyEvent_SHIFT_MASK) == 0) {
theKeyEquivalent = [theKeyEquivalent lowercaseString];
}
-
+
// Hack for the question mark -- SHIFT and / means use the question mark.
if ((modifiers & java_awt_event_KeyEvent_SHIFT_MASK) != 0 &&
[theKeyEquivalent isEqualToString:@"/"])
@@ -142,10 +184,10 @@
theKeyEquivalent = @"?";
modifiers &= ~java_awt_event_KeyEvent_SHIFT_MASK;
}
-
+
modifierMask = JavaModifiersToNsKeyModifiers(modifiers, NO);
}
-
+
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
[fMenuItem setKeyEquivalent:theKeyEquivalent];
[fMenuItem setKeyEquivalentModifierMask:modifierMask];
@@ -154,14 +196,14 @@
}
- (void) setJavaImage:(NSImage *)theImage {
-
+
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
[fMenuItem setImage:theImage];
}];
}
- (void) setJavaToolTipText:(NSString *)theText {
-
+
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
[fMenuItem setToolTip:theText];
}];
@@ -169,11 +211,11 @@
- (void)setJavaEnabled:(BOOL) enabled {
-
+
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
@synchronized(self) {
fIsEnabled = enabled;
-
+
// Warning: This won't work if the parent menu is disabled.
// See [CMenu syncFromJava]. We still need to call it here so
// the NSMenuItem itself gets properly updated.
@@ -183,7 +225,7 @@
}
- (BOOL)isEnabled {
-
+
BOOL enabled = NO;
@synchronized(self) {
enabled = fIsEnabled;
@@ -193,7 +235,7 @@
- (void)setJavaState:(BOOL)newState {
-
+
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
[fMenuItem setState:(newState ? NSOnState : NSOffState)];
}];
@@ -207,7 +249,7 @@
- (void)dealloc {
[fMenuItem release];
fMenuItem = nil;
-
+
[super dealloc];
}
@@ -240,7 +282,7 @@
/** Convert a Java keycode for SetMenuItemCmd */
static unichar AWTKeyToMacShortcut(jint awtKey, BOOL doShift) {
unichar macKey = 0;
-
+
if ((awtKey >= java_awt_event_KeyEvent_VK_0 && awtKey <= java_awt_event_KeyEvent_VK_9) ||
(awtKey >= java_awt_event_KeyEvent_VK_A && awtKey <= java_awt_event_KeyEvent_VK_Z))
{
@@ -255,68 +297,68 @@
} else {
// Special characters
switch (awtKey) {
- case java_awt_event_KeyEvent_VK_BACK_QUOTE : macKey = '`'; break;
- case java_awt_event_KeyEvent_VK_QUOTE : macKey = '\''; break;
-
- case java_awt_event_KeyEvent_VK_ESCAPE : macKey = 0x1B; break;
- case java_awt_event_KeyEvent_VK_SPACE : macKey = ' '; break;
- case java_awt_event_KeyEvent_VK_PAGE_UP : macKey = NSPageUpFunctionKey; break;
- case java_awt_event_KeyEvent_VK_PAGE_DOWN : macKey = NSPageDownFunctionKey; break;
- case java_awt_event_KeyEvent_VK_END : macKey = NSEndFunctionKey; break;
- case java_awt_event_KeyEvent_VK_HOME : macKey = NSHomeFunctionKey; break;
-
- case java_awt_event_KeyEvent_VK_LEFT : macKey = NSLeftArrowFunctionKey; break;
- case java_awt_event_KeyEvent_VK_UP : macKey = NSUpArrowFunctionKey; break;
- case java_awt_event_KeyEvent_VK_RIGHT : macKey = NSRightArrowFunctionKey; break;
- case java_awt_event_KeyEvent_VK_DOWN : macKey = NSDownArrowFunctionKey; break;
-
- case java_awt_event_KeyEvent_VK_COMMA : macKey = ','; break;
-
- // Mac OS doesn't distinguish between the two '-' keys...
- case java_awt_event_KeyEvent_VK_MINUS :
- case java_awt_event_KeyEvent_VK_SUBTRACT : macKey = '-'; break;
-
- // or the two '.' keys...
- case java_awt_event_KeyEvent_VK_DECIMAL :
- case java_awt_event_KeyEvent_VK_PERIOD : macKey = '.'; break;
-
- // or the two '/' keys.
- case java_awt_event_KeyEvent_VK_DIVIDE :
- case java_awt_event_KeyEvent_VK_SLASH : macKey = '/'; break;
-
- case java_awt_event_KeyEvent_VK_SEMICOLON : macKey = ';'; break;
- case java_awt_event_KeyEvent_VK_EQUALS : macKey = '='; break;
-
- case java_awt_event_KeyEvent_VK_OPEN_BRACKET : macKey = '['; break;
- case java_awt_event_KeyEvent_VK_BACK_SLASH : macKey = '\\'; break;
- case java_awt_event_KeyEvent_VK_CLOSE_BRACKET : macKey = ']'; break;
-
- case java_awt_event_KeyEvent_VK_MULTIPLY : macKey = '*'; break;
- case java_awt_event_KeyEvent_VK_ADD : macKey = '+'; break;
-
- case java_awt_event_KeyEvent_VK_HELP : macKey = NSHelpFunctionKey; break;
- case java_awt_event_KeyEvent_VK_TAB : macKey = NSTabCharacter; break;
- case java_awt_event_KeyEvent_VK_ENTER : macKey = NSNewlineCharacter; break;
- case java_awt_event_KeyEvent_VK_BACK_SPACE : macKey = NSBackspaceCharacter; break;
- case java_awt_event_KeyEvent_VK_DELETE : macKey = NSDeleteCharacter; break;
- case java_awt_event_KeyEvent_VK_CLEAR : macKey = NSClearDisplayFunctionKey; break;
- case java_awt_event_KeyEvent_VK_AMPERSAND : macKey = '&'; break;
- case java_awt_event_KeyEvent_VK_ASTERISK : macKey = '*'; break;
- case java_awt_event_KeyEvent_VK_QUOTEDBL : macKey = '\"'; break;
- case java_awt_event_KeyEvent_VK_LESS : macKey = '<'; break;
- case java_awt_event_KeyEvent_VK_GREATER : macKey = '>'; break;
- case java_awt_event_KeyEvent_VK_BRACELEFT : macKey = '{'; break;
- case java_awt_event_KeyEvent_VK_BRACERIGHT : macKey = '}'; break;
- case java_awt_event_KeyEvent_VK_AT : macKey = '@'; break;
- case java_awt_event_KeyEvent_VK_COLON : macKey = ':'; break;
- case java_awt_event_KeyEvent_VK_CIRCUMFLEX : macKey = '^'; break;
- case java_awt_event_KeyEvent_VK_DOLLAR : macKey = '$'; break;
- case java_awt_event_KeyEvent_VK_EXCLAMATION_MARK : macKey = '!'; break;
- case java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS : macKey = '('; break;
- case java_awt_event_KeyEvent_VK_NUMBER_SIGN : macKey = '#'; break;
- case java_awt_event_KeyEvent_VK_PLUS : macKey = '+'; break;
- case java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS: macKey = ')'; break;
- case java_awt_event_KeyEvent_VK_UNDERSCORE : macKey = '_'; break;
+ case java_awt_event_KeyEvent_VK_BACK_QUOTE : macKey = '`'; break;
+ case java_awt_event_KeyEvent_VK_QUOTE : macKey = '\''; break;
+
+ case java_awt_event_KeyEvent_VK_ESCAPE : macKey = 0x1B; break;
+ case java_awt_event_KeyEvent_VK_SPACE : macKey = ' '; break;
+ case java_awt_event_KeyEvent_VK_PAGE_UP : macKey = NSPageUpFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_PAGE_DOWN : macKey = NSPageDownFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_END : macKey = NSEndFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_HOME : macKey = NSHomeFunctionKey; break;
+
+ case java_awt_event_KeyEvent_VK_LEFT : macKey = NSLeftArrowFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_UP : macKey = NSUpArrowFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_RIGHT : macKey = NSRightArrowFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_DOWN : macKey = NSDownArrowFunctionKey; break;
+
+ case java_awt_event_KeyEvent_VK_COMMA : macKey = ','; break;
+
+ // Mac OS doesn't distinguish between the two '-' keys...
+ case java_awt_event_KeyEvent_VK_MINUS :
+ case java_awt_event_KeyEvent_VK_SUBTRACT : macKey = '-'; break;
+
+ // or the two '.' keys...
+ case java_awt_event_KeyEvent_VK_DECIMAL :
+ case java_awt_event_KeyEvent_VK_PERIOD : macKey = '.'; break;
+
+ // or the two '/' keys.
+ case java_awt_event_KeyEvent_VK_DIVIDE :
+ case java_awt_event_KeyEvent_VK_SLASH : macKey = '/'; break;
+
+ case java_awt_event_KeyEvent_VK_SEMICOLON : macKey = ';'; break;
+ case java_awt_event_KeyEvent_VK_EQUALS : macKey = '='; break;
+
+ case java_awt_event_KeyEvent_VK_OPEN_BRACKET : macKey = '['; break;
+ case java_awt_event_KeyEvent_VK_BACK_SLASH : macKey = '\\'; break;
+ case java_awt_event_KeyEvent_VK_CLOSE_BRACKET : macKey = ']'; break;
+
+ case java_awt_event_KeyEvent_VK_MULTIPLY : macKey = '*'; break;
+ case java_awt_event_KeyEvent_VK_ADD : macKey = '+'; break;
+
+ case java_awt_event_KeyEvent_VK_HELP : macKey = NSHelpFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_TAB : macKey = NSTabCharacter; break;
+ case java_awt_event_KeyEvent_VK_ENTER : macKey = NSNewlineCharacter; break;
+ case java_awt_event_KeyEvent_VK_BACK_SPACE : macKey = NSBackspaceCharacter; break;
+ case java_awt_event_KeyEvent_VK_DELETE : macKey = NSDeleteCharacter; break;
+ case java_awt_event_KeyEvent_VK_CLEAR : macKey = NSClearDisplayFunctionKey; break;
+ case java_awt_event_KeyEvent_VK_AMPERSAND : macKey = '&'; break;
+ case java_awt_event_KeyEvent_VK_ASTERISK : macKey = '*'; break;
+ case java_awt_event_KeyEvent_VK_QUOTEDBL : macKey = '\"'; break;
+ case java_awt_event_KeyEvent_VK_LESS : macKey = '<'; break;
+ case java_awt_event_KeyEvent_VK_GREATER : macKey = '>'; break;
+ case java_awt_event_KeyEvent_VK_BRACELEFT : macKey = '{'; break;
+ case java_awt_event_KeyEvent_VK_BRACERIGHT : macKey = '}'; break;
+ case java_awt_event_KeyEvent_VK_AT : macKey = '@'; break;
+ case java_awt_event_KeyEvent_VK_COLON : macKey = ':'; break;
+ case java_awt_event_KeyEvent_VK_CIRCUMFLEX : macKey = '^'; break;
+ case java_awt_event_KeyEvent_VK_DOLLAR : macKey = '$'; break;
+ case java_awt_event_KeyEvent_VK_EXCLAMATION_MARK : macKey = '!'; break;
+ case java_awt_event_KeyEvent_VK_LEFT_PARENTHESIS : macKey = '('; break;
+ case java_awt_event_KeyEvent_VK_NUMBER_SIGN : macKey = '#'; break;
+ case java_awt_event_KeyEvent_VK_PLUS : macKey = '+'; break;
+ case java_awt_event_KeyEvent_VK_RIGHT_PARENTHESIS: macKey = ')'; break;
+ case java_awt_event_KeyEvent_VK_UNDERSCORE : macKey = '_'; break;
}
}
return macKey;
@@ -330,27 +372,27 @@
JNIEXPORT void JNICALL
Java_sun_lwawt_macosx_CMenuItem_nativeSetLabel
(JNIEnv *env, jobject peer,
- jlong menuItemObj, jstring label,
- jchar shortcutKey, jint shortcutKeyCode, jint mods)
+ jlong menuItemObj, jstring label,
+ jchar shortcutKey, jint shortcutKeyCode, jint mods)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
NSString *theLabel = JNFJavaToNSString(env, label);
NSString *theKeyEquivalent = nil;
unichar macKey = shortcutKey;
-
+
if (macKey == 0) {
macKey = AWTKeyToMacShortcut(shortcutKeyCode, (mods & java_awt_event_KeyEvent_SHIFT_MASK) != 0);
}
-
+
if (macKey != 0) {
unichar equivalent[1] = {macKey};
theKeyEquivalent = [NSString stringWithCharacters:equivalent length:1];
} else {
theKeyEquivalent = @"";
}
-
+
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaLabel:theLabel shortcut:theKeyEquivalent modifierMask:mods];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
/*
@@ -362,10 +404,10 @@
Java_sun_lwawt_macosx_CMenuItem_nativeSetTooltip
(JNIEnv *env, jobject peer, jlong menuItemObj, jstring tooltip)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
NSString *theTooltip = JNFJavaToNSString(env, tooltip);
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaToolTipText:theTooltip];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
/*
@@ -377,9 +419,9 @@
Java_sun_lwawt_macosx_CMenuItem_nativeSetImage
(JNIEnv *env, jobject peer, jlong menuItemObj, jlong image)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
[((CMenuItem *)jlong_to_ptr(menuItemObj)) setJavaImage:(NSImage*)jlong_to_ptr(image)];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
/*
@@ -389,38 +431,38 @@
*/
JNIEXPORT jlong JNICALL
Java_sun_lwawt_macosx_CMenuItem_nativeCreate
- (JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
+(JNIEnv *env, jobject peer, jlong parentCMenuObj, jboolean isSeparator)
{
-
+
CMenuItem *aCMenuItem = nil;
CMenu *parentCMenu = (CMenu *)jlong_to_ptr(parentCMenuObj);
-JNF_COCOA_ENTER(env);
-
+ JNF_COCOA_ENTER(env);
+
jobject cPeerObjGlobal = (*env)->NewGlobalRef(env, peer);
-
+
NSMutableArray *args = nil;
-
+
// Create a new item....
if (isSeparator == JNI_TRUE) {
args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:YES], nil];
} else {
args = [[NSMutableArray alloc] initWithObjects:[NSValue valueWithBytes:&cPeerObjGlobal objCType:@encode(jobject)], [NSNumber numberWithBool:NO], nil];
}
-
+
[ThreadUtilities performOnMainThread:@selector(_createMenuItem_OnAppKitThread:) on:[CMenuItem alloc] withObject:args waitUntilDone:YES];
-
+
aCMenuItem = (CMenuItem *)[args objectAtIndex: 0];
-
+
if (aCMenuItem == nil) {
return 0L;
}
-
+
// and add it to the parent item.
[parentCMenu addJavaMenuItem: aCMenuItem];
-
+
// setLabel will be called after creation completes.
-
-JNF_COCOA_EXIT(env);
+
+ JNF_COCOA_EXIT(env);
return ptr_to_jlong(aCMenuItem);
}
@@ -433,10 +475,10 @@
Java_sun_lwawt_macosx_CMenuItem_nativeSetEnabled
(JNIEnv *env, jobject peer, jlong menuItemObj, jboolean enable)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
[item setJavaEnabled: (enable == JNI_TRUE)];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
/*
@@ -448,10 +490,10 @@
Java_sun_lwawt_macosx_CCheckboxMenuItem_nativeSetState
(JNIEnv *env, jobject peer, jlong menuItemObj, jboolean state)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
[item setJavaState: (state == JNI_TRUE)];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
/*
@@ -463,8 +505,8 @@
Java_sun_lwawt_macosx_CCheckboxMenuItem_nativeSetIsCheckbox
(JNIEnv *env, jobject peer, jlong menuItemObj)
{
-JNF_COCOA_ENTER(env);
+ JNF_COCOA_ENTER(env);
CMenuItem *item = (CMenuItem *)jlong_to_ptr(menuItemObj);
[item setIsCheckbox];
-JNF_COCOA_EXIT(env);
+ JNF_COCOA_EXIT(env);
}
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java Wed Jan 06 14:54:24 2016 +0000
@@ -874,13 +874,13 @@
return chroma;
}
- boolean idsAreJFIF = true;
+ boolean idsAreJFIF = false;
- for (int i = 0; i < sof.componentSpecs.length; i++) {
- int id = sof.componentSpecs[i].componentId;
- if ((id < 1) || (id >= sof.componentSpecs.length)) {
- idsAreJFIF = false;
- }
+ int cid0 = sof.componentSpecs[0].componentId;
+ int cid1 = sof.componentSpecs[1].componentId;
+ int cid2 = sof.componentSpecs[2].componentId;
+ if ((cid0 == 1) && (cid1 == 2) && (cid2 == 3)) {
+ idsAreJFIF = true;
}
if (idsAreJFIF) {
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/png/PNGImageWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -193,7 +193,17 @@
// Return to end of chunk and flush to minimize buffering
stream.seek(pos);
- stream.flushBefore(pos);
+ try {
+ stream.flushBefore(pos);
+ } catch (IOException e) {
+ /*
+ * If flushBefore() fails we try to access startPos in finally
+ * block of write_IDAT(). We should update startPos to avoid
+ * IndexOutOfBoundException while seek() is happening.
+ */
+ this.startPos = stream.getStreamPosition();
+ throw e;
+ }
}
public int read() throws IOException {
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java Wed Jan 06 14:54:24 2016 +0000
@@ -472,6 +472,14 @@
// Read tag number, value type, and value count.
int tagNumber = stream.readUnsignedShort();
int type = stream.readUnsignedShort();
+ int sizeOfType;
+ try {
+ sizeOfType = TIFFTag.getSizeOfType(type);
+ } catch (IllegalArgumentException ignored) {
+ // Continue with the next IFD entry.
+ stream.skipBytes(4);
+ continue;
+ }
int count = (int)stream.readUnsignedInt();
// Get the associated TIFFTag.
@@ -510,14 +518,14 @@
}
}
- int size = count*TIFFTag.getSizeOfType(type);
+ int size = count*sizeOfType;
if (size > 4 || tag.isIFDPointer()) {
// The IFD entry value is a pointer to the actual field value.
long offset = stream.readUnsignedInt();
// Check whether the the field value is within the stream.
if (haveStreamLength && offset + size > streamLength) {
- throw new IIOException("Field data is past end-of-stream");
+ continue;
}
// Add a TIFFIFDEntry as a placeholder. This avoids a mark,
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -205,6 +205,10 @@
// Next available space.
private long nextSpace = 0L;
+ private long prevStreamPosition;
+ private long prevHeaderPosition;
+ private long prevNextSpace;
+
// Whether a sequence is being written.
private boolean isWritingSequence = false;
private boolean isInsertingEmpty = false;
@@ -2300,7 +2304,14 @@
public void write(IIOMetadata sm,
IIOImage iioimage,
ImageWriteParam p) throws IOException {
+ if (stream == null) {
+ throw new IllegalStateException("output == null!");
+ }
+ markPositions();
write(sm, iioimage, p, true, true);
+ if (abortRequested()) {
+ resetPositions();
+ }
}
private void writeHeader() throws IOException {
@@ -2333,7 +2344,7 @@
throw new IllegalStateException("output == null!");
}
if (iioimage == null) {
- throw new NullPointerException("image == null!");
+ throw new IllegalArgumentException("image == null!");
}
if(iioimage.hasRaster() && !canWriteRasters()) {
throw new UnsupportedOperationException
@@ -2767,7 +2778,7 @@
throw new IllegalStateException("Output not set!");
}
if (image == null) {
- throw new NullPointerException("image == null!");
+ throw new IllegalArgumentException("image == null!");
}
// Locate the position of the old IFD (ifd) and the location
@@ -2779,9 +2790,16 @@
// imageIndex is < -1 or is too big thereby satisfying the spec.
locateIFD(imageIndex, ifdpos, ifd);
+ markPositions();
+
// Seek to the position containing the pointer to the old IFD.
stream.seek(ifdpos[0]);
+ // Save the previous pointer value in case of abort.
+ stream.mark();
+ long prevPointerValue = stream.readUnsignedInt();
+ stream.reset();
+
// Update next space pointer in anticipation of next write.
if(ifdpos[0] + 4 > nextSpace) {
nextSpace = ifdpos[0] + 4;
@@ -2805,6 +2823,12 @@
// Update the new IFD to point to the old IFD.
stream.writeInt((int)ifd[0]);
// Don't need to update nextSpace here as already done in write().
+
+ if (abortRequested()) {
+ stream.seek(ifdpos[0]);
+ stream.writeInt((int)prevPointerValue);
+ resetPositions();
+ }
}
// ----- BEGIN insert/writeEmpty methods -----
@@ -2834,7 +2858,7 @@
}
if(imageType == null) {
- throw new NullPointerException("imageType == null!");
+ throw new IllegalArgumentException("imageType == null!");
}
if(width < 1 || height < 1) {
@@ -2891,6 +2915,10 @@
IIOMetadata imageMetadata,
List<? extends BufferedImage> thumbnails,
ImageWriteParam param) throws IOException {
+ if (stream == null) {
+ throw new IllegalStateException("output == null!");
+ }
+
checkParamsEmpty(imageType, width, height, thumbnails);
this.isWritingEmpty = true;
@@ -2901,8 +2929,12 @@
0, 0, emptySM.getWidth(), emptySM.getHeight(),
emptySM, imageType.getColorModel());
+ markPositions();
write(streamMetadata, new IIOImage(emptyImage, null, imageMetadata),
param, true, false);
+ if (abortRequested()) {
+ resetPositions();
+ }
}
public void endInsertEmpty() throws IOException {
@@ -3015,7 +3047,7 @@
throw new IllegalStateException("Output not set!");
}
if (region == null) {
- throw new NullPointerException("region == null!");
+ throw new IllegalArgumentException("region == null!");
}
if (region.getWidth() < 1) {
throw new IllegalArgumentException("region.getWidth() < 1!");
@@ -3200,7 +3232,7 @@
}
if (image == null) {
- throw new NullPointerException("image == null!");
+ throw new IllegalArgumentException("image == null!");
}
if (!inReplacePixelsNest) {
@@ -3559,6 +3591,20 @@
// ----- END replacePixels methods -----
+ // Save stream positions for use when aborted.
+ private void markPositions() throws IOException {
+ prevStreamPosition = stream.getStreamPosition();
+ prevHeaderPosition = headerPosition;
+ prevNextSpace = nextSpace;
+ }
+
+ // Reset to positions saved by markPositions().
+ private void resetPositions() throws IOException {
+ stream.seek(prevStreamPosition);
+ headerPosition = prevHeaderPosition;
+ nextSpace = prevNextSpace;
+ }
+
public void reset() {
super.reset();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2014, 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
@@ -25,10 +25,11 @@
package com.sun.media.sound;
+import java.util.Objects;
+
import javax.sound.midi.MidiDevice;
import javax.sound.midi.spi.MidiDeviceProvider;
-
/**
* Super class for MIDI input or output device provider.
*
@@ -127,7 +128,8 @@
}
@Override
- public final MidiDevice getDevice(MidiDevice.Info info) {
+ public final MidiDevice getDevice(final MidiDevice.Info info) {
+ Objects.requireNonNull(info);
if (info instanceof Info) {
readDeviceInfos();
MidiDevice[] devices = getDeviceCache();
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JARSoundbankReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -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.io.BufferedReader;
@@ -32,6 +33,8 @@
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
+import java.util.Objects;
+
import javax.sound.midi.InvalidMidiDataException;
import javax.sound.midi.Soundbank;
import javax.sound.midi.spi.SoundbankReader;
@@ -112,6 +115,7 @@
public Soundbank getSoundbank(InputStream stream)
throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(stream);
return null;
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -25,6 +25,8 @@
package com.sun.media.sound;
+import java.util.Objects;
+
import javax.sound.midi.MidiDevice;
import javax.sound.midi.spi.MidiDeviceProvider;
@@ -42,6 +44,7 @@
@Override
public MidiDevice getDevice(final MidiDevice.Info info) {
+ Objects.requireNonNull(info);
if (RealTimeSequencer.info.equals(info)) {
return new RealTimeSequencer();
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -25,6 +25,8 @@
package com.sun.media.sound;
+import java.util.Objects;
+
import javax.sound.midi.MidiDevice;
import javax.sound.midi.spi.MidiDeviceProvider;
@@ -42,6 +44,7 @@
@Override
public MidiDevice getDevice(final MidiDevice.Info info) {
+ Objects.requireNonNull(info);
if (SoftSynthesizer.info.equals(info)) {
return new SoftSynthesizer();
}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -25,21 +25,22 @@
package com.sun.media.sound;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.SequenceInputStream;
import java.io.File;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.InputStream;
-import java.io.IOException;
import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.SequenceInputStream;
+import java.util.Objects;
import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
import javax.sound.midi.MidiEvent;
-import javax.sound.midi.MetaMessage;
import javax.sound.midi.Sequence;
import javax.sound.midi.ShortMessage;
import javax.sound.midi.SysexMessage;
@@ -115,24 +116,16 @@
return typesArray;
}
- public boolean isFileTypeSupported(int type) {
- for(int i=0; i<types.length; i++) {
- if( type == types[i] ) {
- return true;
- }
+ public int write(Sequence in, int type, OutputStream out) throws IOException {
+ Objects.requireNonNull(out);
+ if (!isFileTypeSupported(type, in)) {
+ throw new IllegalArgumentException("Could not write MIDI file");
}
- return false;
- }
-
- public int write(Sequence in, int type, OutputStream out) throws IOException {
byte [] buffer = null;
int bytesRead = 0;
long bytesWritten = 0;
- if( !isFileTypeSupported(type,in) ) {
- throw new IllegalArgumentException("Could not write MIDI file");
- }
// First get the fileStream from this sequence
InputStream fileStream = getFileStream(type,in);
if (fileStream == null) {
@@ -149,6 +142,7 @@
}
public int write(Sequence in, int type, File out) throws IOException {
+ Objects.requireNonNull(in);
FileOutputStream fos = new FileOutputStream(out); // throws IOException
int bytesWritten = write( in, type, fos );
fos.close();
--- a/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/java/awt/TextComponent.java Wed Jan 06 14:54:24 2016 +0000
@@ -229,15 +229,21 @@
* @see java.awt.TextComponent#getText
*/
public synchronized void setText(String t) {
- boolean skipTextEvent = (text == null || text.isEmpty())
- && (t == null || t.isEmpty());
- text = (t != null) ? t : "";
+ if (t == null) {
+ t = "";
+ }
TextComponentPeer peer = (TextComponentPeer)this.peer;
- // Please note that we do not want to post an event
- // if TextArea.setText() or TextField.setText() replaces an empty text
- // by an empty text, that is, if component's text remains unchanged.
- if (peer != null && !skipTextEvent) {
- peer.setText(text);
+ if (peer != null) {
+ text = peer.getText();
+ // Please note that we do not want to post an event
+ // if TextArea.setText() or TextField.setText() replaces text
+ // by same text, that is, if component's text remains unchanged.
+ if (!t.equals(text)) {
+ text = t;
+ peer.setText(text);
+ }
+ } else {
+ text = t;
}
}
--- a/jdk/src/java.desktop/share/classes/java/awt/TextField.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/java/awt/TextField.java Wed Jan 06 14:54:24 2016 +0000
@@ -198,7 +198,7 @@
* @see java.awt.GraphicsEnvironment#isHeadless
*/
public TextField(String text, int columns) throws HeadlessException {
- super(text);
+ super(replaceEOL(text));
this.columns = (columns >= 0) ? columns : 0;
}
@@ -297,13 +297,32 @@
* @see java.awt.TextComponent#getText
*/
public void setText(String t) {
- super.setText(t);
+ super.setText(replaceEOL(t));
// This could change the preferred size of the Component.
invalidateIfValid();
}
/**
+ * Replaces EOL characters from the text variable with a space character.
+ * @param text the new text.
+ * @return Returns text after replacing EOL characters.
+ */
+ private static String replaceEOL(String text) {
+ if (text == null) {
+ return text;
+ }
+ String[] strEOLs = {System.lineSeparator(), "\n"};
+ for (String eol : strEOLs) {
+ if (text.contains(eol)) {
+ text = text.replace(eol, " ");
+ }
+ }
+ return text;
+ }
+
+
+ /**
* Indicates whether or not this text field has a
* character set for echoing.
* <p>
@@ -704,6 +723,7 @@
{
// HeadlessException will be thrown by TextComponent's readObject
s.defaultReadObject();
+ text = replaceEOL(text);
// Make sure the state we just read in for columns has legal values
if (columns < 0) {
--- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageIO.java Wed Jan 06 14:54:24 2016 +0000
@@ -564,9 +564,12 @@
if (stream != null) {
stream.mark();
}
- canDecode = spi.canDecodeInput(input);
- if (stream != null) {
- stream.reset();
+ try {
+ canDecode = spi.canDecodeInput(input);
+ } finally {
+ if (stream != null) {
+ stream.reset();
+ }
}
return canDecode;
--- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -35,6 +35,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.Properties;
import java.util.Set;
@@ -179,10 +180,12 @@
* due to resource restrictions
* @throws IllegalArgumentException if the info object does not represent a
* MIDI device installed on the system
+ * @throws NullPointerException if {@code info} is {@code null}
* @see #getMidiDeviceInfo
*/
public static MidiDevice getMidiDevice(final MidiDevice.Info info)
throws MidiUnavailableException {
+ Objects.requireNonNull(info);
for (final MidiDeviceProvider provider : getMidiDeviceProviders()) {
if (provider.isDeviceSupported(info)) {
return provider.getDevice(info);
@@ -447,11 +450,13 @@
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
+ * @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
- public static Soundbank getSoundbank(InputStream stream)
- throws InvalidMidiDataException, IOException {
+ public static Soundbank getSoundbank(final InputStream stream)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(stream);
SoundbankReader sp = null;
Soundbank s = null;
@@ -479,9 +484,11 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
+ * @throws NullPointerException if {@code url} is {@code null}
*/
- public static Soundbank getSoundbank(URL url)
- throws InvalidMidiDataException, IOException {
+ public static Soundbank getSoundbank(final URL url)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(url);
SoundbankReader sp = null;
Soundbank s = null;
@@ -509,9 +516,11 @@
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI soundbank data recognized by the system
* @throws IOException if an I/O error occurred when loading the soundbank
+ * @throws NullPointerException if {@code file} is {@code null}
*/
- public static Soundbank getSoundbank(File file)
- throws InvalidMidiDataException, IOException {
+ public static Soundbank getSoundbank(final File file)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(file);
SoundbankReader sp = null;
Soundbank s = null;
@@ -556,13 +565,15 @@
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the
* stream
+ * @throws NullPointerException if {@code stream} is {@code null}
* @see #getMidiFileFormat(URL)
* @see #getMidiFileFormat(File)
* @see InputStream#markSupported
* @see InputStream#mark
*/
- public static MidiFileFormat getMidiFileFormat(InputStream stream)
- throws InvalidMidiDataException, IOException {
+ public static MidiFileFormat getMidiFileFormat(final InputStream stream)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(stream);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
@@ -602,11 +613,13 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the URL
+ * @throws NullPointerException if {@code url} is {@code null}
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(File)
*/
- public static MidiFileFormat getMidiFileFormat(URL url)
- throws InvalidMidiDataException, IOException {
+ public static MidiFileFormat getMidiFileFormat(final URL url)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(url);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
@@ -646,11 +659,13 @@
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the file
+ * @throws NullPointerException if {@code file} is {@code null}
* @see #getMidiFileFormat(InputStream)
* @see #getMidiFileFormat(URL)
*/
- public static MidiFileFormat getMidiFileFormat(File file)
- throws InvalidMidiDataException, IOException {
+ public static MidiFileFormat getMidiFileFormat(final File file)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(file);
List<MidiFileReader> providers = getMidiFileReaders();
MidiFileFormat format = null;
@@ -699,11 +714,13 @@
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the stream
+ * @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
- public static Sequence getSequence(InputStream stream)
- throws InvalidMidiDataException, IOException {
+ public static Sequence getSequence(final InputStream stream)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(stream);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
@@ -743,9 +760,11 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs while accessing the URL
+ * @throws NullPointerException if {@code url} is {@code null}
*/
- public static Sequence getSequence(URL url)
- throws InvalidMidiDataException, IOException {
+ public static Sequence getSequence(final URL url)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(url);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
@@ -787,9 +806,11 @@
* @throws InvalidMidiDataException if the File does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code file} is {@code null}
*/
- public static Sequence getSequence(File file)
- throws InvalidMidiDataException, IOException {
+ public static Sequence getSequence(final File file)
+ throws InvalidMidiDataException, IOException {
+ Objects.requireNonNull(file);
List<MidiFileReader> providers = getMidiFileReaders();
Sequence sequence = null;
@@ -870,8 +891,10 @@
* @param sequence the sequence for which MIDI file type support is queried
* @return the set of unique supported file types. If no file types are
* supported, returns an array of length 0.
+ * @throws NullPointerException if {@code sequence} is {@code null}
*/
- public static int[] getMidiFileTypes(Sequence sequence) {
+ public static int[] getMidiFileTypes(final Sequence sequence) {
+ Objects.requireNonNull(sequence);
List<MidiFileWriter> providers = getMidiFileWriters();
Set<Integer> allTypes = new HashSet<>();
@@ -903,8 +926,11 @@
* @param sequence the sequence for which file writing support is queried
* @return {@code true} if the file type is supported for this sequence,
* otherwise {@code false}
+ * @throws NullPointerException if {@code sequence} is {@code null}
*/
- public static boolean isFileTypeSupported(int fileType, Sequence sequence) {
+ public static boolean isFileTypeSupported(final int fileType,
+ final Sequence sequence) {
+ Objects.requireNonNull(sequence);
List<MidiFileWriter> providers = getMidiFileWriters();
@@ -929,10 +955,15 @@
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file format is not supported by
* the system
+ * @throws NullPointerException if {@code in} or {@code out} are
+ * {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
- public static int write(Sequence in, int fileType, OutputStream out) throws IOException {
+ public static int write(final Sequence in, final int fileType,
+ final OutputStream out) throws IOException {
+ Objects.requireNonNull(in);
+ Objects.requireNonNull(out);
List<MidiFileWriter> providers = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
@@ -963,10 +994,15 @@
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by the
* system
+ * @throws NullPointerException if {@code in} or {@code out} are
+ * {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
- public static int write(Sequence in, int type, File out) throws IOException {
+ public static int write(final Sequence in, final int type, final File out)
+ throws IOException {
+ Objects.requireNonNull(in);
+ Objects.requireNonNull(out);
List<MidiFileWriter> providers = getMidiFileWriters();
//$$fb 2002-04-17: Fix for 4635287: Standard MidiFileWriter cannot write empty Sequences
--- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -26,6 +26,7 @@
package javax.sound.midi.spi;
import java.util.Arrays;
+import java.util.Objects;
import javax.sound.midi.MidiDevice;
@@ -46,8 +47,10 @@
* is queried
* @return {@code true} if the specified device is supported, otherwise
* {@code false}
+ * @throws NullPointerException if {@code info} is {@code null}
*/
public boolean isDeviceSupported(final MidiDevice.Info info) {
+ Objects.requireNonNull(info);
return Arrays.asList(getDeviceInfo()).contains(info);
}
@@ -67,6 +70,7 @@
* @throws IllegalArgumentException if the info object specified does not
* match the info object for a device supported by this
* {@code MidiDeviceProvider}
+ * @throws NullPointerException if {@code info} is {@code null}
*/
public abstract MidiDevice getDevice(MidiDevice.Info info);
}
--- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -60,6 +60,7 @@
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
@@ -76,6 +77,7 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code url} is {@code null}
*/
public abstract MidiFileFormat getMidiFileFormat(URL url)
throws InvalidMidiDataException, IOException;
@@ -90,6 +92,7 @@
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code file} is {@code null}
*/
public abstract MidiFileFormat getMidiFileFormat(File file)
throws InvalidMidiDataException, IOException;
@@ -110,6 +113,7 @@
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code stream} is {@code null}
* @see InputStream#markSupported
* @see InputStream#mark
*/
@@ -126,6 +130,7 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code url} is {@code null}
*/
public abstract Sequence getSequence(URL url)
throws InvalidMidiDataException, IOException;
@@ -141,6 +146,7 @@
* @throws InvalidMidiDataException if the {@code File} does not point to
* valid MIDI file data recognized by the system
* @throws IOException if an I/O exception occurs
+ * @throws NullPointerException if {@code file} is {@code null}
*/
public abstract Sequence getSequence(File file)
throws InvalidMidiDataException, IOException;
--- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -58,6 +58,7 @@
* queried
* @return array of file types. If no file types are supported, returns an
* array of length 0.
+ * @throws NullPointerException if {@code sequence} is {@code null}
*/
public abstract int[] getMidiFileTypes(Sequence sequence);
@@ -88,6 +89,7 @@
* @param sequence the sequence for which file writing support is queried
* @return {@code true} if the file type is supported for this sequence,
* otherwise {@code false}
+ * @throws NullPointerException if {@code sequence} is {@code null}
*/
public boolean isFileTypeSupported(int fileType, Sequence sequence) {
@@ -111,6 +113,8 @@
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by
* this file writer
+ * @throws NullPointerException if {@code in} or {@code out} are
+ * {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
@@ -129,6 +133,8 @@
* @throws IOException if an I/O exception occurs
* @throws IllegalArgumentException if the file type is not supported by
* this file writer
+ * @throws NullPointerException if {@code in} or {@code out} are
+ * {@code null}
* @see #isFileTypeSupported(int, Sequence)
* @see #getMidiFileTypes(Sequence)
*/
--- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -52,6 +52,7 @@
* @throws InvalidMidiDataException if the URL does not point to valid MIDI
* soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
+ * @throws NullPointerException if {@code url} is {@code null}
*/
public abstract Soundbank getSoundbank(URL url)
throws InvalidMidiDataException, IOException;
@@ -64,6 +65,7 @@
* @throws InvalidMidiDataException if the stream does not point to valid
* MIDI soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
+ * @throws NullPointerException if {@code stream} is {@code null}
*/
public abstract Soundbank getSoundbank(InputStream stream)
throws InvalidMidiDataException, IOException;
@@ -76,6 +78,7 @@
* @throws InvalidMidiDataException if the file does not point to valid MIDI
* soundbank data recognized by this soundbank reader
* @throws IOException if an I/O error occurs
+ * @throws NullPointerException if {@code file} is {@code null}
*/
public abstract Soundbank getSoundbank(File file)
throws InvalidMidiDataException, IOException;
--- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java Wed Jan 06 14:54:24 2016 +0000
@@ -618,6 +618,7 @@
* @return the {@code ComponentUI} object that renders this component
* @since 1.9
*/
+ @Transient
public ComponentUI getUI() {
return ui;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java Wed Jan 06 14:54:24 2016 +0000
@@ -663,7 +663,9 @@
if(newFolder.exists()) {
throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
} else {
- newFolder.mkdirs();
+ if(!newFolder.mkdirs()) {
+ throw new IOException(newFolder.getAbsolutePath());
+ }
}
return newFolder;
@@ -773,7 +775,9 @@
if(newFolder.exists()) {
throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
} else {
- newFolder.mkdirs();
+ if(!newFolder.mkdirs()) {
+ throw new IOException(newFolder.getAbsolutePath());
+ }
}
return newFolder;
@@ -842,9 +846,10 @@
if(newFolder.exists()) {
throw new IOException("Directory already exists:" + newFolder.getAbsolutePath());
} else {
- newFolder.mkdirs();
+ if(!newFolder.mkdirs()) {
+ throw new IOException(newFolder.getAbsolutePath());
+ }
}
-
return newFolder;
}
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,6 +36,7 @@
import sun.font.BidiUtils;
import sun.swing.SwingUtilities2;
+import sun.swing.text.UndoableEditLockSupport;
/**
* An implementation of the document interface to serve as a
@@ -275,6 +276,11 @@
* @see EventListenerList
*/
protected void fireUndoableEditUpdate(UndoableEditEvent e) {
+ if (e.getEdit() instanceof DefaultDocumentEvent) {
+ e = new UndoableEditEvent(e.getSource(),
+ new DefaultDocumentEventUndoableWrapper(
+ (DefaultDocumentEvent)e.getEdit()));
+ }
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
@@ -2952,6 +2958,88 @@
}
+ static class DefaultDocumentEventUndoableWrapper implements
+ UndoableEdit, UndoableEditLockSupport
+ {
+ final DefaultDocumentEvent dde;
+ public DefaultDocumentEventUndoableWrapper(DefaultDocumentEvent dde) {
+ this.dde = dde;
+ }
+
+ @Override
+ public void undo() throws CannotUndoException {
+ dde.undo();
+ }
+
+ @Override
+ public boolean canUndo() {
+ return dde.canUndo();
+ }
+
+ @Override
+ public void redo() throws CannotRedoException {
+ dde.redo();
+ }
+
+ @Override
+ public boolean canRedo() {
+ return dde.canRedo();
+ }
+
+ @Override
+ public void die() {
+ dde.die();
+ }
+
+ @Override
+ public boolean addEdit(UndoableEdit anEdit) {
+ return dde.addEdit(anEdit);
+ }
+
+ @Override
+ public boolean replaceEdit(UndoableEdit anEdit) {
+ return dde.replaceEdit(anEdit);
+ }
+
+ @Override
+ public boolean isSignificant() {
+ return dde.isSignificant();
+ }
+
+ @Override
+ public String getPresentationName() {
+ return dde.getPresentationName();
+ }
+
+ @Override
+ public String getUndoPresentationName() {
+ return dde.getUndoPresentationName();
+ }
+
+ @Override
+ public String getRedoPresentationName() {
+ return dde.getRedoPresentationName();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public void lockEdit() {
+ ((AbstractDocument)dde.getDocument()).writeLock();
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public void unlockEdit() {
+ ((AbstractDocument)dde.getDocument()).writeUnlock();
+ }
+ }
+
/**
* This event used when firing document changes while Undo/Redo
* operations. It just wraps DefaultDocumentEvent and delegates
--- a/jdk/src/java.desktop/share/classes/javax/swing/undo/UndoManager.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/javax/swing/undo/UndoManager.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -28,6 +28,7 @@
import javax.swing.event.*;
import javax.swing.UIManager;
import java.util.*;
+import sun.swing.text.UndoableEditLockSupport;
/**
* {@code UndoManager} manages a list of {@code UndoableEdits},
@@ -134,6 +135,11 @@
*/
@SuppressWarnings("serial") // Same-version serialization only
public class UndoManager extends CompoundEdit implements UndoableEditListener {
+ private enum Action {
+ UNDO,
+ REDO,
+ ANY
+ }
int indexOfNextAdd;
int limit;
@@ -369,13 +375,8 @@
* @throws CannotRedoException if one of the edits throws
* <code>CannotRedoException</code>
*/
- public synchronized void undoOrRedo() throws CannotRedoException,
- CannotUndoException {
- if (indexOfNextAdd == edits.size()) {
- undo();
- } else {
- redo();
- }
+ public void undoOrRedo() throws CannotRedoException, CannotUndoException {
+ tryUndoOrRedo(Action.ANY);
}
/**
@@ -407,16 +408,8 @@
* @see #canUndo
* @see #editToBeUndone
*/
- public synchronized void undo() throws CannotUndoException {
- if (inProgress) {
- UndoableEdit edit = editToBeUndone();
- if (edit == null) {
- throw new CannotUndoException();
- }
- undoTo(edit);
- } else {
- super.undo();
- }
+ public void undo() throws CannotUndoException {
+ tryUndoOrRedo(Action.UNDO);
}
/**
@@ -452,16 +445,90 @@
* @see #canRedo
* @see #editToBeRedone
*/
- public synchronized void redo() throws CannotRedoException {
- if (inProgress) {
- UndoableEdit edit = editToBeRedone();
- if (edit == null) {
- throw new CannotRedoException();
+ public void redo() throws CannotRedoException {
+ tryUndoOrRedo(Action.REDO);
+ }
+
+ private void tryUndoOrRedo(Action action) {
+ UndoableEditLockSupport lockSupport = null;
+ boolean undo;
+ synchronized (this) {
+ if (action == Action.ANY) {
+ undo = indexOfNextAdd == edits.size();
+ } else {
+ undo = action == Action.UNDO;
+ }
+ if (inProgress) {
+ UndoableEdit edit = undo ? editToBeUndone() : editToBeRedone();
+ if (edit == null) {
+ throw undo ? new CannotUndoException() :
+ new CannotRedoException();
+ }
+ lockSupport = getEditLockSupport(edit);
+ if (lockSupport == null) {
+ if (undo) {
+ undoTo(edit);
+ } else {
+ redoTo(edit);
+ }
+ return;
+ }
+ } else {
+ if (undo) {
+ super.undo();
+ } else {
+ super.redo();
+ }
+ return;
}
- redoTo(edit);
- } else {
- super.redo();
}
+ // the edit synchronization is required
+ while (true) {
+ lockSupport.lockEdit();
+ UndoableEditLockSupport editLockSupport = null;
+ try {
+ synchronized (this) {
+ if (action == Action.ANY) {
+ undo = indexOfNextAdd == edits.size();
+ }
+ if (inProgress) {
+ UndoableEdit edit = undo ? editToBeUndone() :
+ editToBeRedone();
+ if (edit == null) {
+ throw undo ? new CannotUndoException() :
+ new CannotRedoException();
+ }
+ editLockSupport = getEditLockSupport(edit);
+ if (editLockSupport == null ||
+ editLockSupport == lockSupport) {
+ if (undo) {
+ undoTo(edit);
+ } else {
+ redoTo(edit);
+ }
+ return;
+ }
+ } else {
+ if (undo) {
+ super.undo();
+ } else {
+ super.redo();
+ }
+ return;
+ }
+ }
+ } finally {
+ if (lockSupport != null) {
+ lockSupport.unlockEdit();
+ }
+ lockSupport = editLockSupport;
+ }
+ }
+ }
+
+ private UndoableEditLockSupport getEditLockSupport(UndoableEdit anEdit) {
+ return anEdit instanceof UndoableEditLockSupport ?
+ (UndoableEditLockSupport)anEdit : null;
}
/**
--- a/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/applet/AppletPanel.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,6 +38,7 @@
import java.security.*;
import java.util.*;
import java.util.Locale;
+import java.util.concurrent.LinkedBlockingQueue;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.EmbeddedFrame;
@@ -45,7 +46,6 @@
import sun.misc.ManagedLocalsThread;
import sun.misc.MessageUtils;
import sun.misc.PerformanceLogger;
-import sun.misc.Queue;
import sun.security.util.SecurityConstants;
/**
@@ -247,8 +247,7 @@
/**
* AppletEvent Queue
*/
- private Queue<Integer> queue = null;
-
+ private LinkedBlockingQueue<Integer> queue = null;
public synchronized void addAppletListener(AppletListener l) {
listeners = AppletEventMulticaster.add(listeners, l);
@@ -276,10 +275,9 @@
synchronized(this) {
if (queue == null) {
//System.out.println("SEND0= " + id);
- queue = new Queue<>();
+ queue = new LinkedBlockingQueue<>();
}
- Integer eventId = Integer.valueOf(id);
- queue.enqueue(eventId);
+ boolean inserted = queue.add(id);
notifyAll();
}
if (id == APPLET_QUIT) {
@@ -303,8 +301,8 @@
while (queue == null || queue.isEmpty()) {
wait();
}
- Integer eventId = queue.dequeue();
- return new AppletEvent(this, eventId.intValue(), null);
+ int eventId = queue.take();
+ return new AppletEvent(this, eventId, null);
}
boolean emptyEventQueue() {
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/SunVolatileImage.java Wed Jan 06 14:54:24 2016 +0000
@@ -70,6 +70,10 @@
{
this.comp = comp;
this.graphicsConfig = graphicsConfig;
+ if (width <= 0 || height <= 0) {
+ throw new IllegalArgumentException("Width (" + width + ")" +
+ " and height (" + height + ") cannot be <= 0");
+ }
this.width = width;
this.height = height;
this.forcedAccelSurfaceType = accType;
--- a/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java Wed Jan 06 14:54:24 2016 +0000
@@ -445,13 +445,19 @@
}
public void setGlyphPosition(int ix, Point2D pos) {
+ if (ix < 0 || ix > glyphs.length) {
+ throw new IndexOutOfBoundsException("ix = " + ix);
+ }
+
initPositions();
int ix2 = ix << 1;
positions[ix2] = (float)pos.getX();
positions[ix2 + 1] = (float)pos.getY();
- clearCaches(ix);
+ if (ix < glyphs.length) {
+ clearCaches(ix);
+ }
addFlags(FLAG_HAS_POSITION_ADJUSTMENTS);
}
--- a/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/font/TrueTypeFont.java Wed Jan 06 14:54:24 2016 +0000
@@ -176,6 +176,13 @@
private String localeFamilyName;
private String localeFullName;
+ public TrueTypeFont(String platname, Object nativeNames, int fIndex,
+ boolean javaRasterizer)
+ throws FontFormatException
+ {
+ this(platname, nativeNames, fIndex, javaRasterizer, true);
+ }
+
/**
* - does basic verification of the file
* - reads the header table for this font (within a collection)
@@ -186,14 +193,17 @@
* or fails verification, or there's no usable cmap
*/
public TrueTypeFont(String platname, Object nativeNames, int fIndex,
- boolean javaRasterizer)
+ boolean javaRasterizer, boolean useFilePool)
throws FontFormatException {
super(platname, nativeNames);
useJavaRasterizer = javaRasterizer;
fontRank = Font2D.TTF_RANK;
try {
- verify();
+ verify(useFilePool);
init(fIndex);
+ if (!useFilePool) {
+ close();
+ }
} catch (Throwable t) {
close();
if (t instanceof FontFormatException) {
@@ -280,6 +290,10 @@
}
+ private synchronized FileChannel open() throws FontFormatException {
+ return open(true);
+ }
+
/* This is intended to be called, and the returned value used,
* from within a block synchronized on this font object.
* ie the channel returned may be nulled out at any time by "close()"
@@ -287,7 +301,8 @@
* Deadlock warning: FontManager.addToPool(..) acquires a global lock,
* which means nested locks may be in effect.
*/
- private synchronized FileChannel open() throws FontFormatException {
+ private synchronized FileChannel open(boolean usePool)
+ throws FontFormatException {
if (disposerRecord.channel == null) {
if (FontUtilities.isLogging()) {
FontUtilities.getLogger().info("open TTF: " + platName);
@@ -306,9 +321,11 @@
});
disposerRecord.channel = raf.getChannel();
fileSize = (int)disposerRecord.channel.size();
- FontManager fm = FontManagerFactory.getInstance();
- if (fm instanceof SunFontManager) {
- ((SunFontManager) fm).addToPool(this);
+ if (usePool) {
+ FontManager fm = FontManagerFactory.getInstance();
+ if (fm instanceof SunFontManager) {
+ ((SunFontManager) fm).addToPool(this);
+ }
}
} catch (NullPointerException e) {
close();
@@ -492,8 +509,8 @@
}
}
- private void verify() throws FontFormatException {
- open();
+ private void verify(boolean usePool) throws FontFormatException {
+ open(usePool);
}
/* sizes, in bytes, of TT/TTC header records */
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ArrayCache.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ArrayCache.java Wed Jan 06 14:54:24 2016 +0000
@@ -166,18 +166,31 @@
* @return new array size
*/
public static int getNewSize(final int curSize, final int needSize) {
+ // check if needSize is negative or integer overflow:
+ if (needSize < 0) {
+ // hard overflow failure - we can't even accommodate
+ // new items without overflowing
+ throw new ArrayIndexOutOfBoundsException(
+ "array exceeds maximum capacity !");
+ }
+ assert curSize >= 0;
final int initial = (curSize & MASK_CLR_1);
int size;
if (initial > THRESHOLD_ARRAY_SIZE) {
size = initial + (initial >> 1); // x(3/2)
} else {
- size = (initial) << 1; // x2
+ size = (initial << 1); // x2
}
// ensure the new size is >= needed size:
if (size < needSize) {
- // align to 4096:
+ // align to 4096 (may overflow):
size = ((needSize >> 12) + 1) << 12;
}
+ // check integer overflow:
+ if (size < 0) {
+ // resize to maximum capacity:
+ size = Integer.MAX_VALUE;
+ }
return size;
}
@@ -188,26 +201,29 @@
* @return new array size
*/
public static long getNewLargeSize(final long curSize, final long needSize) {
+ // check if needSize is negative or integer overflow:
+ if ((needSize >> 31L) != 0L) {
+ // hard overflow failure - we can't even accommodate
+ // new items without overflowing
+ throw new ArrayIndexOutOfBoundsException(
+ "array exceeds maximum capacity !");
+ }
+ assert curSize >= 0L;
long size;
if (curSize > THRESHOLD_HUGE_ARRAY_SIZE) {
size = curSize + (curSize >> 2L); // x(5/4)
} else if (curSize > THRESHOLD_LARGE_ARRAY_SIZE) {
size = curSize + (curSize >> 1L); // x(3/2)
} else {
- size = curSize << 1L; // x2
+ size = (curSize << 1L); // x2
}
// ensure the new size is >= needed size:
if (size < needSize) {
// align to 4096:
- size = ((needSize >> 12) + 1) << 12;
+ size = ((needSize >> 12L) + 1L) << 12L;
}
- if (size >= Integer.MAX_VALUE) {
- if (curSize >= Integer.MAX_VALUE) {
- // hard overflow failure - we can't even accommodate
- // new items without overflowing
- throw new ArrayIndexOutOfBoundsException(
- "array exceeds maximum capacity !");
- }
+ // check integer overflow:
+ if (size > Integer.MAX_VALUE) {
// resize to maximum capacity:
size = Integer.MAX_VALUE;
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java Wed Jan 06 14:54:24 2016 +0000
@@ -74,7 +74,7 @@
void putDirtyArray(final byte[] array, final int length) {
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
@@ -98,7 +98,7 @@
{
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java Wed Jan 06 14:54:24 2016 +0000
@@ -75,7 +75,7 @@
void putDirtyArray(final float[] array, final int length) {
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
@@ -99,7 +99,7 @@
{
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatMath.java Wed Jan 06 14:54:24 2016 +0000
@@ -24,8 +24,8 @@
*/
package sun.java2d.marlin;
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
+import jdk.internal.math.DoubleConsts;
+import jdk.internal.math.FloatConsts;
/**
* Faster Math ceil / floor routines derived from StrictMath
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java Wed Jan 06 14:54:24 2016 +0000
@@ -74,7 +74,7 @@
void putDirtyArray(final int[] array, final int length) {
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
@@ -98,7 +98,7 @@
{
if (length != arraySize) {
if (doChecks) {
- System.out.println("ArrayCache: bad length = " + length);
+ MarlinUtils.logInfo("ArrayCache: bad length = " + length);
}
return;
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java Wed Jan 06 14:54:24 2016 +0000
@@ -156,8 +156,6 @@
// rewritten to avoid division:
|| (width * heightSubPixel) >
((edgeSumDeltaY - heightSubPixel) << BLOCK_SIZE_LG);
-// ((edgeSumDeltaY - heightSubPixel) * RLE_THRESHOLD);
-// ((edgeSumDeltaY - heightSubPixel) << BLOCK_TH_LG);
if (doTrace && !useRLE) {
final float meanCrossings
@@ -293,8 +291,10 @@
// update row index to current position:
rowAAChunkIndex[row] = pos;
- // determine need array size (may overflow):
- final long needSize = pos + (px_bbox1 - px0);
+ // determine need array size:
+ // for RLE encoding, position must be aligned to 4 bytes (int):
+ // align - 1 = 3 so add +3 and round-off by mask ~3 = -4
+ final long needSize = pos + ((px_bbox1 - px0 + 3) & -4);
// update next position (bytes):
rowAAChunkPos = needSize;
@@ -401,8 +401,7 @@
// determine need array size:
// pessimistic: max needed size = deltaX x 4 (1 int)
- final int maxLen = (to - from);
- final long needSize = initialPos + (maxLen << 2);
+ final long needSize = initialPos + ((to - from) << 2);
// update row data:
OffHeapArray _rowAAChunk = rowAAChunk;
@@ -465,6 +464,13 @@
// note: last pixel exclusive (>= 0)
// note: it should check X is smaller than 23bits (overflow)!
+ // check address alignment to 4 bytes:
+ if (doCheckUnsafe) {
+ if ((addr_off & 3) != 0) {
+ MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
+ }
+ }
+
// special case to encode entries into a single int:
if (val == 0) {
_unsafe.putInt(addr_off,
@@ -521,6 +527,13 @@
// note: last pixel exclusive (>= 0)
// note: it should check X is smaller than 23bits (overflow)!
+ // check address alignment to 4 bytes:
+ if (doCheckUnsafe) {
+ if ((addr_off & 3) != 0) {
+ MarlinUtils.logInfo("Misaligned Unsafe address: " + addr_off);
+ }
+ }
+
// special case to encode entries into a single int:
if (val == 0) {
_unsafe.putInt(addr_off,
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinConst.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinConst.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,8 +30,8 @@
*/
interface MarlinConst {
// enable Logs (logger or stdout)
- static final boolean enableLogs = false;
- // enable Logger
+ static final boolean enableLogs = MarlinProperties.isLoggingEnabled();
+ // use Logger instead of stdout
static final boolean useLogger = enableLogs && MarlinProperties.isUseLogger();
// log new RendererContext
@@ -40,14 +40,17 @@
// log misc.Unsafe alloc/realloc/free
static final boolean logUnsafeMalloc = enableLogs
&& MarlinProperties.isLogUnsafeMalloc();
+ // do check unsafe alignment:
+ static final boolean doCheckUnsafe = false;
// do statistics
static final boolean doStats = enableLogs && MarlinProperties.isDoStats();
// do monitors
// disabled to reduce byte-code size a bit...
- static final boolean doMonitors = enableLogs && false; // MarlinProperties.isDoMonitors();
+ static final boolean doMonitors = false;
+// static final boolean doMonitors = enableLogs && MarlinProperties.isDoMonitors();
// do checks
- static final boolean doChecks = false; // MarlinProperties.isDoChecks();
+ static final boolean doChecks = enableLogs && MarlinProperties.isDoChecks();
// do AA range checks: disable when algorithm / code is stable
static final boolean DO_AA_RANGE_CHECK = false;
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinProperties.java Wed Jan 06 14:54:24 2016 +0000
@@ -136,6 +136,10 @@
// logging parameters
+ public static boolean isLoggingEnabled() {
+ return getBoolean("sun.java2d.renderer.log", "false");
+ }
+
public static boolean isUseLogger() {
return getBoolean("sun.java2d.renderer.useLogger", "false");
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinUtils.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinUtils.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,12 +27,12 @@
public final class MarlinUtils {
- // TODO: use sun.util.logging.PlatformLogger once in JDK9
- private static final java.util.logging.Logger log;
+ // Marlin logger
+ private static final sun.util.logging.PlatformLogger log;
static {
if (MarlinConst.useLogger) {
- log = java.util.logging.Logger.getLogger("sun.java2d.marlin");
+ log = sun.util.logging.PlatformLogger.getLogger("sun.java2d.marlin");
} else {
log = null;
}
@@ -53,25 +53,11 @@
public static void logException(final String msg, final Throwable th) {
if (MarlinConst.useLogger) {
-// log.warning(msg, th);
- log.log(java.util.logging.Level.WARNING, msg, th);
+ log.warning(msg, th);
} else if (MarlinConst.enableLogs) {
System.out.print("WARNING: ");
System.out.println(msg);
th.printStackTrace(System.err);
}
}
-
- // Returns the caller's class and method's name; best effort
- // if cannot infer, return the logger's name.
- static String getCallerInfo(String className) {
- String sourceClassName = null;
- String sourceMethodName = null;
-
- if (sourceClassName != null) {
- return sourceClassName + " " + sourceMethodName;
- } else {
- return "unknown";
- }
- }
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java Wed Jan 06 14:54:24 2016 +0000
@@ -629,6 +629,13 @@
}
if (edgeMinY != Float.POSITIVE_INFINITY) {
+ // if context is maked as DIRTY:
+ if (rdrCtx.dirty) {
+ // may happen if an exception if thrown in the pipeline processing:
+ // clear completely buckets arrays:
+ buckets_minY = 0;
+ buckets_maxY = boundsMaxY - boundsMinY;
+ }
// clear used part
if (edgeBuckets == edgeBuckets_initial) {
// fill only used part
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,7 +31,6 @@
import java.util.concurrent.atomic.AtomicInteger;
import static sun.java2d.marlin.ArrayCache.*;
import sun.java2d.marlin.MarlinRenderingEngine.NormalizingPathIterator;
-import static sun.java2d.marlin.MarlinUtils.getCallerInfo;
import static sun.java2d.marlin.MarlinUtils.logInfo;
/**
@@ -39,7 +38,6 @@
*/
final class RendererContext implements MarlinConst {
- private static final String className = RendererContext.class.getName();
// RendererContext creation counter
private static final AtomicInteger contextCount = new AtomicInteger(1);
// RendererContext statistics
@@ -214,8 +212,7 @@
}
if (doLogOverSize) {
- logInfo("getDirtyByteArray[oversize]: length=\t" + length
- + "\tfrom=\t" + getCallerInfo(className));
+ logInfo("getDirtyByteArray[oversize]: length=\t" + length);
}
return new byte[length];
@@ -254,7 +251,7 @@
if (doLogWidenArray) {
logInfo("widenDirtyByteArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
- + needSize + "\tfrom=\t" + getCallerInfo(className));
+ + needSize);
}
return res;
}
@@ -275,8 +272,7 @@
}
if (doLogOverSize) {
- logInfo("getIntArray[oversize]: length=\t" + length + "\tfrom=\t"
- + getCallerInfo(className));
+ logInfo("getIntArray[oversize]: length=\t" + length);
}
return new int[length];
@@ -306,7 +302,7 @@
if (doLogWidenArray) {
logInfo("widenIntArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
- + needSize + "\tfrom=\t" + getCallerInfo(className));
+ + needSize);
}
return res;
}
@@ -338,8 +334,7 @@
}
if (doLogOverSize) {
- logInfo("getDirtyIntArray[oversize]: length=\t" + length
- + "\tfrom=\t" + getCallerInfo(className));
+ logInfo("getDirtyIntArray[oversize]: length=\t" + length);
}
return new int[length];
@@ -369,7 +364,7 @@
if (doLogWidenArray) {
logInfo("widenDirtyIntArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
- + needSize + "\tfrom=\t" + getCallerInfo(className));
+ + needSize);
}
return res;
}
@@ -399,8 +394,7 @@
}
if (doLogOverSize) {
- logInfo("getDirtyFloatArray[oversize]: length=\t" + length
- + "\tfrom=\t" + getCallerInfo(className));
+ logInfo("getDirtyFloatArray[oversize]: length=\t" + length);
}
return new float[length];
@@ -430,7 +424,7 @@
if (doLogWidenArray) {
logInfo("widenDirtyFloatArray[" + res.length + "]: usedSize=\t"
+ usedSize + "\tlength=\t" + length + "\tneeded length=\t"
- + needSize + "\tfrom=\t" + getCallerInfo(className));
+ + needSize);
}
return res;
}
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererStats.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,8 @@
package sun.java2d.marlin;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -32,6 +34,7 @@
import sun.java2d.marlin.stats.Histogram;
import sun.java2d.marlin.stats.Monitor;
import sun.java2d.marlin.stats.StatLong;
+import sun.awt.util.ThreadGroupUtils;
/**
* This class gathers global rendering statistics for debugging purposes only
@@ -237,22 +240,33 @@
private RendererStats() {
super();
- Runtime.getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- dump();
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<Void>) () -> {
+ final Thread hook = new Thread(
+ ThreadGroupUtils.getRootThreadGroup(),
+ new Runnable() {
+ @Override
+ public void run() {
+ dump();
+ }
+ },
+ "MarlinStatsHook"
+ );
+ hook.setContextClassLoader(null);
+ Runtime.getRuntime().addShutdownHook(hook);
- if (useDumpThread) {
- final Timer statTimer = new Timer("RendererStats");
- statTimer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- dump();
+ if (useDumpThread) {
+ final Timer statTimer = new Timer("RendererStats");
+ statTimer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ dump();
+ }
+ }, statDump, statDump);
}
- }, statDump, statDump);
- }
+ return null;
+ }
+ );
}
void dump() {
--- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java Wed Jan 06 14:54:24 2016 +0000
@@ -1265,14 +1265,15 @@
}
private void ensureSpace(final int n) {
- if (end + n > curves.length) {
+ // use substraction to avoid integer overflow:
+ if (curves.length - end < n) {
if (doStats) {
RendererContext.stats.stat_array_stroker_polystack_curves
.add(end + n);
}
curves = rdrCtx.widenDirtyFloatArray(curves, end, end + n);
}
- if (numCurves + 1 > curveTypes.length) {
+ if (curveTypes.length <= numCurves) {
if (doStats) {
RendererContext.stats.stat_array_stroker_polystack_curveTypes
.add(numCurves + 1);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/sun/swing/text/UndoableEditLockSupport.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,43 @@
+/*
+ * 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.swing.text;
+
+import javax.swing.undo.UndoableEdit;
+
+/**
+ * UndoableEdit support for undo/redo actions synchronization
+ * @since 1.9
+ */
+public interface UndoableEditLockSupport extends UndoableEdit {
+ /**
+ * lock the UndoableEdit for threadsafe undo/redo
+ */
+ void lockEdit();
+
+ /**
+ * unlock the UndoableEdit
+ */
+ void unlockEdit();
+}
--- a/jdk/src/java.desktop/share/native/libfontmanager/FontInstanceAdapter.cpp Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libfontmanager/FontInstanceAdapter.cpp Wed Jan 06 14:54:24 2016 +0000
@@ -67,12 +67,6 @@
};
-const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
-{
- size_t ignored = 0;
- return getFontTable(tableTag, ignored);
-}
-
static const LETag cacheMap[LAYOUTCACHE_ENTRIES] = {
GPOS_TAG, GDEF_TAG, GSUB_TAG, MORT_TAG, MORX_TAG, KERN_TAG
};
--- a/jdk/src/java.desktop/share/native/libfontmanager/FontInstanceAdapter.h Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libfontmanager/FontInstanceAdapter.h Wed Jan 06 14:54:24 2016 +0000
@@ -85,7 +85,6 @@
// tables are cached with the native font scaler data
// only supports gsub, gpos, gdef, mort tables at present
- virtual const void *getFontTable(LETag tableTag) const;
virtual const void *getFontTable(LETag tableTag, size_t &len) const;
virtual void *getKernPairs() const {
--- a/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libfontmanager/HBShaper.c Wed Jan 06 14:54:24 2016 +0000
@@ -80,15 +80,18 @@
float scale = 1.0f/64.0f;
unsigned int* glyphs;
float* positions;
+ int initialCount, glyphArrayLen, posArrayLen, maxGlyphs, storeadv;
+ unsigned int* indices;
+ jarray glyphArray, posArray, inxArray;
if (!init_JNI_IDs(env)) {
return 0;
}
- int initialCount = (*env)->GetIntField(env, gvdata, gvdCountFID);
- jarray glyphArray =
+ initialCount = (*env)->GetIntField(env, gvdata, gvdCountFID);
+ glyphArray =
(jarray)(*env)->GetObjectField(env, gvdata, gvdGlyphsFID);
- jarray posArray =
+ posArray =
(jarray)(*env)->GetObjectField(env, gvdata, gvdPositionsFID);
if (glyphArray == NULL || posArray == NULL)
@@ -101,9 +104,9 @@
// and re-invokes layout. I suppose this is expected to be rare
// because at least in a single threaded case there should be
// re-use of the same container, but it is a little wasteful/distateful.
- int glyphArrayLen = (*env)->GetArrayLength(env, glyphArray);
- int posArrayLen = (*env)->GetArrayLength(env, posArray);
- int maxGlyphs = glyphCount + initialCount;
+ glyphArrayLen = (*env)->GetArrayLength(env, glyphArray);
+ posArrayLen = (*env)->GetArrayLength(env, posArray);
+ maxGlyphs = glyphCount + initialCount;
if ((maxGlyphs > glyphArrayLen) ||
(maxGlyphs * 2 + 2 > posArrayLen))
{
@@ -125,7 +128,7 @@
x += glyphPos[i].x_advance * scale;
y += glyphPos[i].y_advance * scale;
}
- int storeadv = initialCount+glyphCount;
+ storeadv = initialCount+glyphCount;
// The final slot in the positions array is important
// because when the GlyphVector is created from this
// data it determines the overall advance of the glyphvector
@@ -138,11 +141,10 @@
(*env)->ReleasePrimitiveArrayCritical(env, glyphArray, glyphs, 0);
(*env)->ReleasePrimitiveArrayCritical(env, posArray, positions, 0);
putFloat(env, startPt,positions[(storeadv*2)],positions[(storeadv*2)+1] );
- jarray inxArray =
+ inxArray =
(jarray)(*env)->GetObjectField(env, gvdata, gvdIndicesFID);
- unsigned int* indices =
+ indices =
(unsigned int*)(*env)->GetPrimitiveArrayCritical(env, inxArray, NULL);
- int prevCluster = -1;
for (i = 0; i < glyphCount; i++) {
int cluster = glyphInfo[i].cluster;
if (direction == HB_DIRECTION_LTR) {
--- a/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c Wed Jan 06 14:54:24 2016 +0000
@@ -258,7 +258,7 @@
scalerInfo->fontData,
scalerInfo->fontDataLength);
if (bBuffer != NULL) {
- (*env)->CallObjectMethod(env, font2D,
+ (*env)->CallVoidMethod(env, font2D,
sunFontIDs.readFileMID, bBuffer);
error = FT_New_Memory_Face(scalerInfo->library,
--- a/jdk/src/java.desktop/share/native/libfontmanager/layout/LEFontInstance.h Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/LEFontInstance.h Wed Jan 06 14:54:24 2016 +0000
@@ -181,28 +181,6 @@
*
* Subclasses which represent composite fonts should always return <code>NULL</code>.
*
- * Note that implementing this function does not allow for range checking.
- * Subclasses that desire the safety of range checking must implement the
- * variation which has a length parameter.
- *
- * @param tableTag - the four byte table tag. (e.g. 'cmap')
- *
- * @return the address of the table in memory, or <code>NULL</code>
- * if the table doesn't exist.
- *
- * @stable ICU 2.8
- */
- virtual const void *getFontTable(LETag tableTag) const = 0;
-
- /**
- * This method reads a table from the font. Note that in general,
- * it only makes sense to call this method on an <code>LEFontInstance</code>
- * which represents a physical font - i.e. one which has been returned by
- * <code>getSubFont()</code>. This is because each subfont in a composite font
- * will have different tables, and there's no way to know which subfont to access.
- *
- * Subclasses which represent composite fonts should always return <code>NULL</code>.
- *
* This version sets a length, for range checking.
* Note that range checking can only be accomplished if this function is
* implemented in subclasses.
@@ -213,7 +191,7 @@
* if the table doesn't exist.
* @internal
*/
- virtual const void* getFontTable(LETag tableTag, size_t &length) const { length=-1; return getFontTable(tableTag); } /* -1 = unknown length */
+ virtual const void* getFontTable(LETag tableTag, size_t &length) const = 0;
virtual void *getKernPairs() const = 0;
virtual void setKernPairs(void *pairs) const = 0;
--- a/jdk/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/share/native/libjavajpeg/imageioJPEG.c Wed Jan 06 14:54:24 2016 +0000
@@ -1610,6 +1610,7 @@
int ret;
int h_samp0, h_samp1, h_samp2;
int v_samp0, v_samp1, v_samp2;
+ int cid0, cid1, cid2;
jboolean retval = JNI_FALSE;
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_decompress_ptr cinfo;
@@ -1711,17 +1712,15 @@
}
} else if (!cinfo->saw_JFIF_marker && !IS_EXIF(cinfo)) {
/*
- * IJG assumes all unidentified 3-channels are YCbCr.
- * We assume that only if the second two channels are
- * subsampled (either horizontally or vertically). If not,
- * we assume RGB.
- *
- * 4776576: Some digital cameras output YCbCr JPEG images
- * that do not contain a JFIF APP0 marker but are only
- * vertically subsampled (no horizontal subsampling).
- * We should only assume this is RGB data if the subsampling
- * factors for the second two channels are the same as the
- * first (check both horizontal and vertical factors).
+ * In the absence of certain markers, IJG has interpreted
+ * component id's of [1,2,3] as meaning YCbCr.We follow that
+ * interpretation, which is additionally described in the Image
+ * I/O JPEG metadata spec.If that condition is not met here the
+ * next step will be to examine the subsampling factors, if
+ * there is any difference in subsampling factors we also assume
+ * YCbCr, only if both horizontal and vertical subsampling
+ * is same we assume JPEG color space as RGB.
+ * This is also described in the Image I/O JPEG metadata spec.
*/
h_samp0 = cinfo->comp_info[0].h_samp_factor;
h_samp1 = cinfo->comp_info[1].h_samp_factor;
@@ -1731,8 +1730,13 @@
v_samp1 = cinfo->comp_info[1].v_samp_factor;
v_samp2 = cinfo->comp_info[2].v_samp_factor;
- if ((h_samp1 == h_samp0) && (h_samp2 == h_samp0) &&
- (v_samp1 == v_samp0) && (v_samp2 == v_samp0))
+ cid0 = cinfo->comp_info[0].component_id;
+ cid1 = cinfo->comp_info[1].component_id;
+ cid2 = cinfo->comp_info[2].component_id;
+
+ if ((!(cid0 == 1 && cid1 == 2 && cid2 == 3)) &&
+ ((h_samp1 == h_samp0) && (h_samp2 == h_samp0) &&
+ (v_samp1 == v_samp0) && (v_samp2 == v_samp0)))
{
cinfo->jpeg_color_space = JCS_RGB;
/* output is already RGB, so it stays the same */
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTrayIconPeer.java Wed Jan 06 14:54:24 2016 +0000
@@ -413,6 +413,7 @@
void addListeners() {
canvas.addMouseListener(eventProxy);
canvas.addMouseMotionListener(eventProxy);
+ eframe.addMouseListener(eventProxy);
}
long getWindow() {
--- a/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java Wed Jan 06 14:54:24 2016 +0000
@@ -926,7 +926,10 @@
return copyflavors;
}
}
- return null;
+ DocFlavor[] flavor = new DocFlavor[2];
+ flavor[0] = DocFlavor.SERVICE_FORMATTED.PAGEABLE;
+ flavor[1] = DocFlavor.SERVICE_FORMATTED.PRINTABLE;
+ return flavor;
}
--- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c Wed Jan 06 14:54:24 2016 +0000
@@ -438,6 +438,15 @@
xsdo->drawable = drawable;
xsdo->isPixmap = JNI_FALSE;
} else {
+ /*
+ * width , height must be nonzero otherwise XCreatePixmap
+ * generates BadValue in error_handler
+ */
+ if (width <= 0 || height <= 0) {
+ JNU_ThrowOutOfMemoryError(env,
+ "Can't create offscreen surface");
+ return JNI_FALSE;
+ }
xsdo->isPixmap = JNI_TRUE;
/* REMIND: workaround for bug 4420220 on pgx32 boards:
don't use DGA with pixmaps unless USE_DGA_PIXMAPS is set.
--- a/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/Win32FontManager.java Wed Jan 06 14:54:24 2016 +0000
@@ -61,7 +61,7 @@
* enumerate (allow direct use) of EUDC fonts.
*/
eudcFont = new TrueTypeFont(eudcFile, null, 0,
- true);
+ true, false);
} catch (FontFormatException e) {
}
}
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,10 +29,12 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.io.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.time.Clock;
import java.util.function.Predicate;
-import static jdk.internal.logger.SimpleConsoleLogger.skipLoggingFrame;
+import static jdk.internal.logger.SimpleConsoleLogger.isFilteredFrame;
/**
* LogRecord objects are used to pass logging requests between
@@ -685,7 +687,12 @@
* CallerFinder is a stateful predicate.
*/
static final class CallerFinder implements Predicate<StackWalker.StackFrame> {
- static final StackWalker WALKER = StackWalker.getInstance();
+ private static final StackWalker WALKER;
+ static {
+ final PrivilegedAction<StackWalker> action =
+ () -> StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
+ WALKER = AccessController.doPrivileged(action);
+ }
/**
* Returns StackFrame of the caller's frame.
@@ -715,8 +722,9 @@
lookingForLogger = !isLoggerImplFrame(cname);
return false;
}
- // skip logging/logger infrastructure and reflection calls
- return !skipLoggingFrame(cname);
+ // Continue walking until we've found the relevant calling frame.
+ // Skips logging/logger infrastructure.
+ return !isFilteredFrame(t);
}
private boolean isLoggerImplFrame(String cname) {
--- a/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.naming/share/classes/com/sun/jndi/ldap/Ber.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,7 @@
import java.io.IOException;
import java.io.ByteArrayInputStream;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* Base class that defines common fields, constants, and debug method.
--- a/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.naming/share/classes/sun/security/provider/certpath/ldap/LDAPCertStoreImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,7 +44,7 @@
import javax.naming.ldap.LdapContext;
import javax.security.auth.x500.X500Principal;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.provider.certpath.X509CertificatePair;
import sun.security.util.Cache;
import sun.security.util.Debug;
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosTicket.java Wed Jan 06 14:54:24 2016 +0000
@@ -34,7 +34,7 @@
import javax.security.auth.Destroyable;
import javax.security.auth.RefreshFailedException;
import javax.security.auth.DestroyFailedException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* This class encapsulates a Kerberos ticket and associated
--- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,7 +30,7 @@
import javax.crypto.SecretKey;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.krb5.Asn1Exception;
import sun.security.krb5.PrincipalName;
import sun.security.krb5.EncryptionKey;
--- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java Wed Jan 06 14:54:24 2016 +0000
@@ -26,7 +26,7 @@
package sun.security.jgss.krb5;
import org.ietf.jgss.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.jgss.GSSUtil;
import sun.security.jgss.GSSCaller;
import sun.security.jgss.spi.*;
@@ -1415,7 +1415,7 @@
@Override
public String toString() {
return "Kerberos session key: etype: " + key.getEType() + "\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(key.getBytes());
+ new HexDumpEncoder().encodeBuffer(key.getBytes());
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/KRBError.java Wed Jan 06 14:54:24 2016 +0000
@@ -227,7 +227,7 @@
} catch (Exception e) {
if (DEBUG) {
System.out.println("Unable to parse eData field of KRB-ERROR:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data));
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data));
}
IOException ioe = new IOException(
"Unable to parse eData field of KRB-ERROR");
@@ -237,7 +237,7 @@
} else {
if (DEBUG) {
System.out.println("Unknown eData field of KRB-ERROR:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data));
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data));
}
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java Wed Jan 06 14:54:24 2016 +0000
@@ -306,8 +306,8 @@
public static final boolean DEBUG =
java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
- public static final sun.misc.HexDumpEncoder hexDumper =
- new sun.misc.HexDumpEncoder();
+ public static final sun.security.util.HexDumpEncoder hexDumper =
+ new sun.security.util.HexDumpEncoder();
static {
errMsgList = new Hashtable<Integer,String> ();
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/PAData.java Wed Jan 06 14:54:24 2016 +0000
@@ -306,7 +306,7 @@
} else if (s2kparams.length == 0) {
sb.append("empty\n");
} else {
- sb.append(new sun.misc.HexDumpEncoder()
+ sb.append(new sun.security.util.HexDumpEncoder()
.encodeBuffer(s2kparams));
}
}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/crypto/dk/DkCrypto.java Wed Jan 06 14:54:24 2016 +0000
@@ -40,7 +40,7 @@
import java.nio.charset.Charset;
import java.nio.CharBuffer;
import java.nio.ByteBuffer;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.krb5.Confounder;
import sun.security.krb5.internal.crypto.KeyUsage;
import sun.security.krb5.KrbCryptoException;
--- a/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/java.security.sasl/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import java.util.logging.Logger;
import java.util.logging.Level;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* The base class used by client and server implementations of SASL
--- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/AWTEventMonitor.java Wed Jan 06 14:54:24 2016 +0000
@@ -48,8 +48,6 @@
@jdk.Exported
public class AWTEventMonitor {
- static private boolean runningOnJDK1_4 = false;
-
/**
* The current component with keyboard focus.
*
@@ -638,15 +636,9 @@
* @see AWTEventMonitor
*/
public AWTEventsListener() {
- String version = System.getProperty("java.version");
- if (version != null) {
- runningOnJDK1_4 = (version.compareTo("1.4") >= 0);
- }
initializeIntrospection();
installListeners();
- if (runningOnJDK1_4) {
- MenuSelectionManager.defaultManager().addChangeListener(this);
- }
+ MenuSelectionManager.defaultManager().addChangeListener(this);
EventQueueMonitor.addTopLevelWindowListener(this);
}
@@ -848,15 +840,7 @@
case EventID.FOCUS:
c.removeFocusListener(this);
c.addFocusListener(this);
-
- if (runningOnJDK1_4) {
- processFocusGained();
-
- } else { // not runningOnJDK1_4
- if ((c != componentWithFocus_private) && c.hasFocus()) {
- componentWithFocus_private = c;
- }
- }
+ processFocusGained();
break;
case EventID.ITEM:
--- a/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java Wed Jan 06 14:54:24 2016 +0000
@@ -140,10 +140,6 @@
// initialize AccessibleRole map
initAccessibleRoleMap();
- // determine which version of the JDK is running
- String version = getJavaVersionProperty();
- debugString("JDK version = "+version);
-
// initialize the methods that map HWNDs and Java top-level
// windows
initHWNDcalls();
@@ -215,9 +211,7 @@
} catch (Exception e) {}
/*
- Build the extendedVirtualNameSearchRoles array list. I chose this method
- because some of the Accessible Roles that need to be added to it are not
- available in all versions of the J2SE that we want to support.
+ Build the extendedVirtualNameSearchRoles array list.
*/
extendedVirtualNameSearchRoles.add (AccessibleRole.COMBO_BOX);
try {
@@ -5919,7 +5913,7 @@
*/
AccessibleRole.UNKNOWN,
- // These roles are only available in JDK 1.4
+ // These roles are available since JDK 1.4
/**
* A STATUS_BAR is an simple component that can contain
--- a/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/Krb5LoginModule.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,7 +44,7 @@
import sun.security.krb5.*;
import sun.security.jgss.krb5.Krb5Util;
import sun.security.krb5.Credentials;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* This {@code LoginModule} authenticates users using
--- a/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.security.jgss/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java Wed Jan 06 14:54:24 2016 +0000
@@ -64,6 +64,6 @@
public String toString() {
return "AuthorizationDataEntry: type="+type+", data=" +
data.length + " bytes:\n" +
- new sun.misc.HexDumpEncoder().encodeBuffer(data);
+ new sun.security.util.HexDumpEncoder().encodeBuffer(data);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/JarFileSystem.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,182 @@
+/*
+ * 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 jdk.nio.zipfs;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+/**
+ * Adds aliasing to ZipFileSystem to support multi-release jar files. An alias map
+ * is created by {@link JarFileSystem#createVersionedLinks(int)}. The map is then
+ * consulted when an entry is looked up in {@link JarFileSystem#getEntry(byte[])}
+ * to determine if the entry has a corresponding versioned entry. If so, the
+ * versioned entry is returned.
+ *
+ * @author Steve Drach
+ */
+
+class JarFileSystem extends ZipFileSystem {
+ private Function<byte[],byte[]> lookup;
+
+ @Override
+ Entry getEntry(byte[] path) throws IOException {
+ // check for an alias to a versioned entry
+ byte[] versionedPath = lookup.apply(path);
+ return versionedPath == null ? super.getEntry(path) : super.getEntry(versionedPath);
+ }
+
+ JarFileSystem(ZipFileSystemProvider provider, Path zfpath, Map<String,?> env)
+ throws IOException {
+ super(provider, zfpath, env);
+ lookup = path -> path; // lookup needs to be set before isMultiReleaseJar is called
+ // because it eventually calls getEntry
+ if (isMultiReleaseJar()) {
+ int version;
+ Object o = env.get("multi-release");
+ if (o instanceof String) {
+ String s = (String)o;
+ if (s.equals("runtime")) {
+ version = sun.misc.Version.jdkMajorVersion(); // fixme waiting for jdk.util.Version
+ } else {
+ version = Integer.parseInt(s);
+ }
+ } else if (o instanceof Integer) {
+ version = (Integer)o;
+ } else if (false /*o instanceof Version*/) { // fixme waiting for jdk.util.Version
+// version = ((Version)o).major();
+ } else {
+ throw new IllegalArgumentException("env parameter must be String, Integer, "
+ + "or Version");
+ }
+ lookup = createVersionedLinks(version < 0 ? 0 : version);
+ setReadOnly();
+ }
+ }
+
+ private boolean isMultiReleaseJar() {
+ try (InputStream is = newInputStream(getBytes("META-INF/MANIFEST.MF"))) {
+ return (new Manifest(is)).getMainAttributes()
+ .containsKey(new Attributes.Name("Multi-Release"));
+ // fixme change line above after JarFile integration to contain Attributes.Name.MULTI_RELEASE
+ } catch (IOException x) {
+ return false;
+ }
+ }
+
+ /**
+ * create a map of aliases for versioned entries, for example:
+ * version/PackagePrivate.class -> META-INF/versions/9/version/PackagePrivate.class
+ * version/PackagePrivate.java -> META-INF/versions/9/version/PackagePrivate.java
+ * version/Version.class -> META-INF/versions/10/version/Version.class
+ * version/Version.java -> META-INF/versions/10/version/Version.java
+ *
+ * then wrap the map in a function that getEntry can use to override root
+ * entry lookup for entries that have corresponding versioned entries
+ */
+ private Function<byte[],byte[]> createVersionedLinks(int version) {
+ HashMap<IndexNode,byte[]> aliasMap = new HashMap<>();
+ getVersionMap(version, getInode(getBytes("META-INF/versions"))).values()
+ .forEach(versionNode -> { // for each META-INF/versions/{n} directory
+ // put all the leaf inodes, i.e. entries, into the alias map
+ // possibly shadowing lower versioned entries
+ walk(versionNode, entryNode -> {
+ byte[] rootName = getRootName(versionNode, entryNode);
+ if (rootName != null) {
+ IndexNode rootNode = getInode(rootName);
+ if (rootNode == null) { // no matching root node, make a virtual one
+ rootNode = IndexNode.keyOf(rootName);
+ }
+ aliasMap.put(rootNode, entryNode.name);
+ }
+ });
+ });
+ return path -> aliasMap.get(IndexNode.keyOf(path));
+ }
+
+ /**
+ * create a sorted version map of version -> inode, for inodes <= max version
+ * 9 -> META-INF/versions/9
+ * 10 -> META-INF/versions/10
+ */
+ private TreeMap<Integer, IndexNode> getVersionMap(int version, IndexNode metaInfVersions) {
+ TreeMap<Integer,IndexNode> map = new TreeMap<>();
+ IndexNode child = metaInfVersions.child;
+ while (child != null) {
+ Integer key = getVersion(child.name, metaInfVersions.name.length);
+ if (key != null && key <= version) {
+ map.put(key, child);
+ }
+ child = child.sibling;
+ }
+ return map;
+ }
+
+ /**
+ * extract the integer version number -- META-INF/versions/9 returns 9
+ */
+ private Integer getVersion(byte[] name, int offset) {
+ try {
+ return Integer.parseInt(getString(Arrays.copyOfRange(name, offset, name.length-1)));
+ } catch (NumberFormatException x) {
+ // ignore this even though it might indicate issues with the JAR structure
+ return null;
+ }
+ }
+
+ /**
+ * walk the IndexNode tree processing all leaf nodes
+ */
+ private void walk(IndexNode inode, Consumer<IndexNode> process) {
+ if (inode == null) return;
+ if (inode.isDir()) {
+ walk(inode.child, process);
+ } else {
+ process.accept(inode);
+ walk(inode.sibling, process);
+ }
+ }
+
+ /**
+ * extract the root name from a versioned entry name
+ * given inode for META-INF/versions/9/foo/bar.class
+ * and prefix META-INF/versions/9/
+ * returns foo/bar.class
+ */
+ private byte[] getRootName(IndexNode prefix, IndexNode inode) {
+ int offset = prefix.name.length;
+ byte[] fullName = inode.name;
+ return Arrays.copyOfRange(fullName, offset, fullName.length);
+ }
+}
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystem.java Wed Jan 06 14:54:24 2016 +0000
@@ -155,6 +155,10 @@
throw new ReadOnlyFileSystemException();
}
+ void setReadOnly() {
+ this.readOnly = true;
+ }
+
@Override
public Iterable<Path> getRootDirectories() {
ArrayList<Path> pathArr = new ArrayList<>();
@@ -320,7 +324,7 @@
beginRead();
try {
ensureOpen();
- e = getEntry0(path);
+ e = getEntry(path);
if (e == null) {
IndexNode inode = getInode(path);
if (inode == null)
@@ -342,7 +346,7 @@
beginWrite();
try {
ensureOpen();
- Entry e = getEntry0(path); // ensureOpen checked
+ Entry e = getEntry(path); // ensureOpen checked
if (e == null)
throw new NoSuchFileException(getString(path));
if (e.type == Entry.CEN)
@@ -445,7 +449,7 @@
beginWrite();
try {
ensureOpen();
- Entry eSrc = getEntry0(src); // ensureOpen checked
+ Entry eSrc = getEntry(src); // ensureOpen checked
if (eSrc == null)
throw new NoSuchFileException(getString(src));
if (eSrc.isDir()) { // spec says to create dst dir
@@ -460,7 +464,7 @@
else if (opt == COPY_ATTRIBUTES)
hasCopyAttrs = true;
}
- Entry eDst = getEntry0(dst);
+ Entry eDst = getEntry(dst);
if (eDst != null) {
if (!hasReplace)
throw new FileAlreadyExistsException(getString(dst));
@@ -521,7 +525,7 @@
beginRead(); // only need a readlock, the "update()" will
try { // try to obtain a writelock when the os is
ensureOpen(); // being closed.
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (e != null) {
if (e.isDir() || hasCreateNew)
throw new FileAlreadyExistsException(getString(path));
@@ -550,7 +554,7 @@
beginRead();
try {
ensureOpen();
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (e == null)
throw new NoSuchFileException(getString(path));
if (e.isDir())
@@ -592,7 +596,7 @@
newOutputStream(path, options.toArray(new OpenOption[0])));
long leftover = 0;
if (options.contains(StandardOpenOption.APPEND)) {
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (e != null && e.size >= 0)
leftover = e.size;
}
@@ -644,7 +648,7 @@
beginRead();
try {
ensureOpen();
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (e == null || e.isDir())
throw new NoSuchFileException(getString(path));
final ReadableByteChannel rbc =
@@ -714,7 +718,7 @@
beginRead();
try {
ensureOpen();
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (forWrite) {
checkWritable();
if (e == null) {
@@ -855,7 +859,7 @@
private Path getTempPathForEntry(byte[] path) throws IOException {
Path tmpPath = createTempFileInSameDirectoryAs(zfpath);
if (path != null) {
- Entry e = getEntry0(path);
+ Entry e = getEntry(path);
if (e != null) {
try (InputStream is = newInputStream(path)) {
Files.copy(is, tmpPath, REPLACE_EXISTING);
@@ -939,7 +943,7 @@
private long getDataPos(Entry e) throws IOException {
if (e.locoff == -1) {
- Entry e2 = getEntry0(e.name);
+ Entry e2 = getEntry(e.name);
if (e2 == null)
throw new ZipException("invalid loc for entry <" + e.name + ">");
e.locoff = e2.locoff;
@@ -1325,7 +1329,7 @@
//System.out.printf("->sync(%s) done!%n", toString());
}
- private IndexNode getInode(byte[] path) {
+ IndexNode getInode(byte[] path) {
if (path == null)
throw new NullPointerException("path");
IndexNode key = IndexNode.keyOf(path);
@@ -1340,7 +1344,7 @@
return inode;
}
- private Entry getEntry0(byte[] path) throws IOException {
+ Entry getEntry(byte[] path) throws IOException {
IndexNode inode = getInode(path);
if (inode instanceof Entry)
return (Entry)inode;
@@ -2096,7 +2100,7 @@
pos += (LOCHDR + nlen + elen);
if ((flag & FLAG_DATADESCR) != 0) {
// Data Descriptor
- Entry e = zipfs.getEntry0(name); // get the size/csize from cen
+ Entry e = zipfs.getEntry(name); // get the size/csize from cen
if (e == null)
throw new ZipException("loc: name not found in cen");
size = e.size;
--- a/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipFileSystemProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -100,7 +100,11 @@
}
ZipFileSystem zipfs = null;
try {
- zipfs = new ZipFileSystem(this, path, env);
+ if (env.containsKey("multi-release")) {
+ zipfs = new JarFileSystem(this, path, env);
+ } else {
+ zipfs = new ZipFileSystem(this, path, env);
+ }
} catch (ZipException ze) {
String pname = path.toString();
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
@@ -124,8 +128,14 @@
throw new UnsupportedOperationException();
}
ensureFile(path);
- try {
- return new ZipFileSystem(this, path, env);
+ try {
+ ZipFileSystem zipfs;
+ if (env.containsKey("multi-release")) {
+ zipfs = new JarFileSystem(this, path, env);
+ } else {
+ zipfs = new ZipFileSystem(this, path, env);
+ }
+ return zipfs;
} catch (ZipException ze) {
String pname = path.toString();
if (pname.endsWith(".zip") || pname.endsWith(".jar"))
--- a/jdk/test/ProblemList.txt Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/ProblemList.txt Wed Jan 06 14:54:24 2016 +0000
@@ -310,8 +310,6 @@
# jdk_imageio
-javax/imageio/plugins/shared/WriteAfterAbort.java generic-all
-
############################################################################
# jdk_swing
--- a/jdk/test/TEST.groups Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/TEST.groups Wed Jan 06 14:54:24 2016 +0000
@@ -95,16 +95,19 @@
-:jdk_concurrent \
-:jdk_stream
-# java.util.concurrent (JSR-166)
+# All collections, core and concurrent
+jdk_collections = \
+ :jdk_collections_core \
+ :jdk_concurrent
+
+# java.util.concurrent
+# Includes concurrent collections plus other stuff
# Maintained by JSR-166 EG (Doug Lea et al)
-# Deque and PriorityQueue are also generally maintained by JSR-166
jdk_concurrent = \
- java/util/concurrent \
- java/util/Deque \
- java/util/PriorityQueue
+ java/util/concurrent
-# Java Collections Framework
-jdk_collections = \
+# Java Collections Framework core classes
+jdk_collections_core = \
java/util/AbstractCollection \
java/util/AbstractList \
java/util/AbstractMap \
@@ -114,19 +117,22 @@
java/util/BitSet \
java/util/Collection \
java/util/Collections \
+ java/util/Comparator \
+ java/util/Deque \
java/util/EnumMap \
java/util/EnumSet \
- java/util/Comparator \
- java/util/Iterator \
java/util/HashMap \
+ java/util/HashSet \
java/util/Hashtable \
java/util/IdentityHashMap \
- java/util/List \
+ java/util/Iterator \
java/util/LinkedHashMap \
java/util/LinkedHashSet \
java/util/LinkedList \
+ java/util/List \
java/util/Map \
java/util/NavigableMap \
+ java/util/PriorityQueue \
java/util/TimSort \
java/util/TreeMap \
java/util/Vector \
--- a/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java Wed Jan 06 14:54:24 2016 +0000
@@ -65,7 +65,10 @@
byte[] aad2 = aad.clone();
aad2[50]++;
- GCMParameterSpec spec = new GCMParameterSpec(128, new byte[16]);
+ byte[] iv = new byte[16];
+ rdm.nextBytes(iv);
+
+ GCMParameterSpec spec = new GCMParameterSpec(128, iv);
Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
encCipher.init(Cipher.ENCRYPT_MODE, key, spec);
encCipher.updateAAD(aad);
--- a/jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java Wed Jan 06 14:54:24 2016 +0000
@@ -126,7 +126,11 @@
}
// Now try to encrypt again using a different parameter; should work
- c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, new byte[30]));
+ byte[] rdm_iv = new byte[30];
+ Random rdm = new Random();
+ rdm.nextBytes(rdm_iv);
+
+ c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, rdm_iv));
c.updateAAD(AAD);
c.doFinal(PT);
// subsequent encryption should fail unless re-init w/ different key+iv
--- a/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,7 +25,6 @@
* @test
* @bug 7146728
* @summary DHKeyAgreement2
- * @modules java.base/sun.misc
* @author Jan Luehe
*/
@@ -38,8 +37,6 @@
import javax.crypto.spec.*;
import javax.crypto.interfaces.*;
-import sun.misc.HexDumpEncoder;
-
/**
* This test utility executes the Diffie-Hellman key agreement protocol
* between 2 parties: Alice and Bob.
--- a/jdk/test/com/sun/jdi/SuspendThreadTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/sun/jdi/SuspendThreadTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,6 +42,7 @@
class SuspendThreadTarg {
public static long count;
+ public static boolean active = true;
public static void bkpt() {
count++;
@@ -53,7 +54,7 @@
// We need this to be running so the bkpt
// can be hit immediately when it is enabled
// in the back-end.
- while(count >= 0) {
+ while(active) {
bkpt();
}
System.out.println("Goodbye from SuspendThreadTarg, count = " + count);
@@ -82,9 +83,9 @@
// to guard against spurious wakeups from bkptSignal.wait()
boolean signalSent;
// signal that a breakpoint has happened
- Object bkptSignal = new Object() {};
+ final private Object bkptSignal = new Object() {};
BreakpointRequest bkptRequest;
- Field debuggeeCountField;
+ Field debuggeeCountField, debuggeeActiveField;
// When we get a bkpt we want to disable the request,
// resume the debuggee, and then re-enable the request
@@ -119,65 +120,71 @@
/********** test core **********/
protected void runTests() throws Exception {
- /*
- * Get to the top of main()
- * to determine targetClass and mainThread
- */
- BreakpointEvent bpe = startToMain("SuspendThreadTarg");
- targetClass = (ClassType)bpe.location().declaringType();
- mainThread = bpe.thread();
- EventRequestManager erm = vm().eventRequestManager();
+ try {
+ /*
+ * Get to the top of main()
+ * to determine targetClass and mainThread
+ */
+ BreakpointEvent bpe = startToMain("SuspendThreadTarg");
+ targetClass = (ClassType)bpe.location().declaringType();
+ mainThread = bpe.thread();
+ EventRequestManager erm = vm().eventRequestManager();
- Location loc1 = findMethod(targetClass, "bkpt", "()V").location();
+ Location loc1 = findMethod(targetClass, "bkpt", "()V").location();
- bkptRequest = erm.createBreakpointRequest(loc1);
+ bkptRequest = erm.createBreakpointRequest(loc1);
- // Without this, it is a SUSPEND_ALL bkpt and the test will pass
- bkptRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
- bkptRequest.enable();
+ // Without this, it is a SUSPEND_ALL bkpt and the test will pass
+ bkptRequest.setSuspendPolicy(EventRequest.SUSPEND_EVENT_THREAD);
+ bkptRequest.enable();
- debuggeeCountField = targetClass.fieldByName("count");
- try {
- addListener (this);
- } catch (Exception ex){
- ex.printStackTrace();
- failure("failure: Could not add listener");
- throw new Exception("SuspendThreadTest: failed", ex);
- }
+ debuggeeCountField = targetClass.fieldByName("count");
+ debuggeeActiveField = targetClass.fieldByName("active");
+ try {
+ addListener (this);
+ } catch (Exception ex){
+ ex.printStackTrace();
+ failure("failure: Could not add listener");
+ throw new Exception("SuspendThreadTest: failed", ex);
+ }
- int prevBkptCount;
- vm().resume();
- synchronized (bkptSignal) {
- while (bkptCount < maxBkpts) {
- prevBkptCount = bkptCount;
- // If we don't get a bkpt within 5 secs,
- // the test fails
- signalSent = false;
- do {
- try {
- bkptSignal.wait(5000);
- } catch (InterruptedException ee) {
+ int prevBkptCount;
+ vm().resume();
+ synchronized (bkptSignal) {
+ while (bkptCount < maxBkpts) {
+ prevBkptCount = bkptCount;
+ // If we don't get a bkpt within 5 secs,
+ // the test fails
+ signalSent = false;
+ do {
+ try {
+ bkptSignal.wait(5000);
+ } catch (InterruptedException ee) {
+ }
+ } while (signalSent == false);
+ if (prevBkptCount == bkptCount) {
+ failure("failure: test hung");
+ break;
}
- } while (signalSent == false);
- if (prevBkptCount == bkptCount) {
- failure("failure: test hung");
- break;
}
}
- }
- println("done with loop");
- bkptRequest.disable();
- removeListener(this);
-
+ println("done with loop");
+ bkptRequest.disable();
+ removeListener(this);
- /*
- * deal with results of test
- * if anything has called failure("foo") testFailed will be true
- */
- if (!testFailed) {
- println("SuspendThreadTest: passed");
- } else {
- throw new Exception("SuspendThreadTest: failed");
+ /*
+ * deal with results of test
+ * if anything has called failure("foo") testFailed will be true
+ */
+ if (!testFailed) {
+ println("SuspendThreadTest: passed");
+ } else {
+ throw new Exception("SuspendThreadTest: failed");
+ }
+ } finally {
+ if (targetClass != null && debuggeeActiveField != null) {
+ targetClass.setValue(debuggeeActiveField, vm().mirrorOf(false));
+ }
}
}
}
--- a/jdk/test/com/sun/jndi/ldap/Base64Test.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/sun/jndi/ldap/Base64Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -164,7 +164,7 @@
private static void deserialize(byte[] bytes) throws Exception {
//System.out.println("\nSerialized RefAddr object: ");
- //System.out.println(new sun.misc.HexDumpEncoder().encode(bytes));
+ //System.out.println(new sun.security.util.HexDumpEncoder().encode(bytes));
ObjectInputStream objectStream =
new ObjectInputStream(new ByteArrayInputStream(bytes));
--- a/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/com/sun/security/sasl/ntlm/NTLMTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,13 +25,14 @@
* @test
* @bug 6911951 7150092
* @summary NTLM should be a supported Java SASL mechanism
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.util
* java.security.sasl
*/
import java.io.IOException;
import javax.security.sasl.*;
import javax.security.auth.callback.*;
import java.util.*;
+import sun.security.util.HexDumpEncoder;
public class NTLMTest {
@@ -311,7 +312,7 @@
byte[] response = (clnt.hasInitialResponse()
? clnt.evaluateChallenge(EMPTY) : EMPTY);
System.out.println("Initial:");
- new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
+ new HexDumpEncoder().encodeBuffer(response, System.out);
byte[] challenge;
while (!clnt.isComplete() || !srv.isComplete()) {
@@ -319,12 +320,12 @@
response = null;
if (challenge != null) {
System.out.println("Challenge:");
- new sun.misc.HexDumpEncoder().encodeBuffer(challenge, System.out);
+ new HexDumpEncoder().encodeBuffer(challenge, System.out);
response = clnt.evaluateChallenge(challenge);
}
if (response != null) {
System.out.println("Response:");
- new sun.misc.HexDumpEncoder().encodeBuffer(response, System.out);
+ new HexDumpEncoder().encodeBuffer(response, System.out);
}
}
--- a/jdk/test/java/awt/List/SetFontTest/SetFontTest.html Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/List/SetFontTest/SetFontTest.html Wed Jan 06 14:54:24 2016 +0000
@@ -38,6 +38,6 @@
<p> See the dialog box (usually in upper left corner) for instructions</p>
-<APPLET CODE="SetFontTest.class" WIDTH=200 HEIGHT=200></APPLET>
+<APPLET CODE="SetFontTest.class" WIDTH=200 HEIGHT=220></APPLET>
</body>
</html>
--- a/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2008, 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 6176814
- @summary Metalworks frame maximizes after the move
- @author Andrei.Dmitriev.Com area=Event
- @run applet MaximizedFrameTest.html
- -->
-<head>
-<title> </title>
-</head>
-<body>
-
-<h1>bug 6176814<br>Bug ID: 6176814 </h1>
-
-<p> This is an AUTOMATIC test, simply wait for completion </p>
-
-<APPLET CODE="MaximizedFrameTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 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
@@ -22,91 +22,149 @@
*/
/*
- test
- @bug 6176814
- @summary Metalworks frame maximizes after the move
- @author Andrei.Dmitriev area=Event
- @run applet MaximizedFrameTest.html
-*/
+ @test
+ @bug 6176814 8132766
+ @summary Metalworks frame maximizes after the move
+ @run main MaximizedFrameTest
+ */
-import java.applet.Applet;
-import javax.swing.*;
-import java.awt.event.*;
-import java.awt.*;
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JFrame;
+import javax.swing.JLayeredPane;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
-public class MaximizedFrameTest extends Applet
-{
- final int ITERATIONS_COUNT = 20;
- Robot robot;
- Point framePosition;
- Point newFrameLocation;
- JFrame frame;
- Rectangle gcBounds;
- public static Object LOCK = new Object();
+public class MaximizedFrameTest {
+
+ final static int ITERATIONS_COUNT = 5;
+ private static JFrame frame;
+ private static Point tempMousePosition;
+ private static Component titleComponent;
- public void init()
- {
- String[] instructions =
- {
- "This is an AUTOMATIC test",
- "simply wait until it is done"
- };
+ public void init() {
JFrame.setDefaultLookAndFeelDecorated(true);
+
+ try {
+ UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
+ } catch (ClassNotFoundException | InstantiationException |
+ IllegalAccessException | UnsupportedLookAndFeelException ex) {
+ throw new RuntimeException("Test Failed. MetalLookAndFeel not set "
+ + "for frame");
+ }
+
frame = new JFrame("JFrame Maximization Test");
frame.pack();
frame.setSize(450, 260);
- }//End init()
+ frame.setVisible(true);
+ }
+
+ public void getTitleComponent() throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ JLayeredPane lPane = frame.getLayeredPane();
+ boolean titleFound = false;
+
+ for (int j = 0; j < lPane.getComponentsInLayer(
+ JLayeredPane.FRAME_CONTENT_LAYER.intValue()).length; j++) {
+
+ titleComponent = lPane.getComponentsInLayer(
+ JLayeredPane.FRAME_CONTENT_LAYER.intValue())[j];
- public void start ()
- {
- frame.setVisible(true);
- validate();
- JLayeredPane lPane = frame.getLayeredPane();
- // System.out.println("JFrame's LayeredPane " + lPane );
- Component titleComponent = null;
- boolean titleFound = false;
- for (int j=0; j < lPane.getComponentsInLayer(JLayeredPane.FRAME_CONTENT_LAYER.intValue()).length; j++){
- titleComponent = lPane.getComponentsInLayer(JLayeredPane.FRAME_CONTENT_LAYER.intValue())[j];
- if (titleComponent.getClass().getName().equals("javax.swing.plaf.metal.MetalTitlePane")){
- titleFound = true;
- break;
+ if (titleComponent.getClass().getName().equals(
+ "javax.swing.plaf.metal.MetalTitlePane")) {
+
+ titleFound = true;
+ break;
+ }
+ }
+
+ if (!titleFound) {
+ try {
+ dispose();
+ } catch (Exception ex) {
+ Logger.getLogger(MaximizedFrameTest.class.getName())
+ .log(Level.SEVERE, null, ex);
+ }
+ throw new RuntimeException("Test Failed. Unable to "
+ + "determine title component");
+ }
}
- }
- if ( !titleFound ){
- throw new RuntimeException("Test Failed. Unable to determine title's size.");
- }
- //--------------------------------
- // it is sufficient to get maximized Frame only once.
- Point tempMousePosition;
- framePosition = frame.getLocationOnScreen();
+ });
+ }
+
+ public void doMaximizeFrameTest() throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ Point framePosition = frame.getLocationOnScreen();
+
+ tempMousePosition = new Point(framePosition.x
+ + frame.getWidth() / 2, framePosition.y
+ + titleComponent.getHeight() / 2);
+ }
+ });
+
try {
- robot = new Robot();
- tempMousePosition = new Point(framePosition.x +
- frame.getWidth()/2,
- framePosition.y +
- titleComponent.getHeight()/2);
+ Robot robot = new Robot();
robot.mouseMove(tempMousePosition.x, tempMousePosition.y);
- for (int iteration=0; iteration < ITERATIONS_COUNT; iteration++){
+ robot.waitForIdle();
+
+ for (int iteration = 0; iteration < ITERATIONS_COUNT; iteration++) {
robot.mousePress(InputEvent.BUTTON1_MASK);
- gcBounds =
- GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[0].getConfigurations()[0].getBounds();
- //Moving a mouse pointer less than a few pixels
- //leads to rising a double click event.
- //We have to use exceeded the AWT_MULTICLICK_SMUDGE
- //const value (which is 4 by default on GNOME) to test that.
+ robot.waitForIdle();
+
+ // Moving a mouse pointer less than a few pixels
+ // leads to rising a double click event.
+ // We have to use exceeded the AWT_MULTICLICK_SMUDGE
+ // const value (which is 4 by default on GNOME) to test that.
tempMousePosition.x += 5;
robot.mouseMove(tempMousePosition.x, tempMousePosition.y);
- robot.delay(70);
+ robot.waitForIdle();
robot.mouseRelease(InputEvent.BUTTON1_MASK);
- if ( frame.getExtendedState() != 0 ){
- throw new RuntimeException ("Test failed. JFrame was maximized. ExtendedState is : "+frame.getExtendedState());
+ robot.waitForIdle();
+
+ if (frame.getExtendedState() != 0) {
+ dispose();
+ throw new RuntimeException("Test failed. JFrame was "
+ + "maximized. ExtendedState is : "
+ + frame.getExtendedState());
}
- robot.delay(500);
- } //for iteration
+ }
+ } catch (AWTException e) {
+ dispose();
+ throw new RuntimeException("Test Failed. AWTException thrown.");
+ }
+ System.out.println("Test passed.");
+ }
- }catch(AWTException e) {
- throw new RuntimeException("Test Failed. AWTException thrown.");
+ private void dispose() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (null != frame) {
+ frame.dispose();
+ }
}
- System.out.println("Test passed.");
- }// start()
-}// class
+ });
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ MaximizedFrameTest maximizedFrameTest = new MaximizedFrameTest();
+ maximizedFrameTest.init();
+ maximizedFrameTest.getTitleComponent();
+ maximizedFrameTest.doMaximizeFrameTest();
+ maximizedFrameTest.dispose();
+ }
+}
--- a/jdk/test/java/awt/TextArea/TextAreaEditing/TextAreaEditing.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TextArea/TextAreaEditing/TextAreaEditing.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,16 +23,23 @@
/*
@test
- @bug 8040322
+ @bug 8040322 8060137
+ @library ../../regtesthelpers
+ @build Util
@summary Test TextArea APIs replaceRange, insert, append & setText
@run main TextAreaEditing
*/
import java.awt.Frame;
+import java.awt.Robot;
import java.awt.TextArea;
+import java.awt.AWTException;
+import java.awt.event.KeyEvent;
+import test.java.awt.regtesthelpers.Util;
public class TextAreaEditing {
+ final static Robot robot = Util.createRobot();
private int testFailCount;
private boolean isTestFail;
private StringBuilder testFailMessage;
@@ -61,6 +68,7 @@
textArea.testReplaceRange();
textArea.testInsert();
textArea.testAppend();
+ textArea.testSetText();
textArea.checkFailures();
textArea.dispose();
}
@@ -119,6 +127,24 @@
checkTest("");
}
+ private void testSetText() {
+ textArea.setText(null);
+ textArea.requestFocus();
+ Util.clickOnComp(textArea, robot);
+ Util.waitForIdle(robot);
+ robot.keyPress(KeyEvent.VK_A);
+ robot.delay(5);
+ robot.keyRelease(KeyEvent.VK_A);
+ Util.waitForIdle(robot);
+ textArea.setText(null);
+ checkTest("");
+ textArea.setText("CaseSensitive");
+ checkTest("CaseSensitive");
+ textArea.setText("caseSensitive");
+ checkTest("caseSensitive");
+
+ }
+
private void checkTest(String str) {
if (str != null && !str.equals(textArea.getText())) {
testFailMessage.append("TestFail line : ");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TextField/EOLTest/EOLTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ */
+
+/*
+ @test
+ @bug 8055197 7186036
+ @summary TextField should replace EOL character with space character
+ @run main EOLTest
+ */
+
+import java.awt.Frame;
+import java.awt.TextField;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
+
+public class EOLTest {
+
+ private Frame mainFrame;
+ private TextField textField;
+ private String testStrEOL;
+ private boolean isTestFail;
+ private int testFailCount;
+ StringBuilder testFailMessage;
+ private String expectedString = "Row1 Row2 Row3";
+
+ public EOLTest() {
+ mainFrame = new Frame();
+ mainFrame.setSize(200, 200);
+ mainFrame.setVisible(true);
+ testFailMessage = new StringBuilder();
+ testStrEOL = "Row1" + System.lineSeparator() + "Row2\nRow3";
+ }
+
+ private void testConstructor1() {
+ textField = new TextField(testStrEOL);
+ textField.setSize(200, 100);
+ mainFrame.add(textField);
+ checkTest();
+ mainFrame.remove(textField);
+ }
+
+ private void testConstructor2() {
+ textField = new TextField(30);
+ textField.setSize(200, 100);
+ mainFrame.add(textField);
+ textField.setText(testStrEOL);
+ checkTest();
+ mainFrame.remove(textField);
+ }
+
+ private void testConstructor3() {
+ textField = new TextField(testStrEOL, 30);
+ textField.setSize(200, 100);
+ mainFrame.add(textField);
+ checkTest();
+ mainFrame.remove(textField);
+ }
+
+ private void testSetText() {
+ textField = new TextField();
+ textField.setSize(200, 100);
+ textField.setText(testStrEOL);
+ mainFrame.add(textField);
+ checkTest();
+ mainFrame.remove(textField);
+ }
+
+ private void testDeserialization() {
+ TextField textFieldToSerialize = new TextField(testStrEOL);
+ textFieldToSerialize.setSize(200, 100);
+ mainFrame.add(textFieldToSerialize);
+ try {
+ // Serialize TextField object "textFieldToSerialize".
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutput outStream = new ObjectOutputStream(baos);
+ outStream.writeObject(textFieldToSerialize);
+
+ // Search the text variable data through serialized object stream.
+ byte[] streamedBytes = baos.toByteArray();
+ int foundLoc = 0;
+ for (int i = 0; i < streamedBytes.length; ++i) {
+ if (streamedBytes[i] == expectedString.charAt(0)) {
+ foundLoc = i;
+ int j = 1;
+ for (; j < expectedString.length(); ++j) {
+ if (streamedBytes[i+j] != expectedString.charAt(j)) {
+ break;
+ }
+ }
+ if (j == expectedString.length()) {
+ break;
+ }
+ }
+ foundLoc = -1;
+ }
+
+ if (foundLoc == -1) {
+ // Could not find text data in serialized object stream.
+ throw new Exception("Could not find text data in serialized "
+ + "object stream.");
+ }
+ // Replace space character from serialized stream with
+ // EOL character for testing de-serialization.
+ String EOLChar = System.lineSeparator();
+ String newExpectedString = "";
+ for (int i = foundLoc, j = 0; j < expectedString.length(); ++i, ++j) {
+ newExpectedString += (char)(streamedBytes[i]);
+ if (streamedBytes[i] == ' ') {
+ int k = 0;
+ for (; k < EOLChar.length(); ++k) {
+ streamedBytes[i + k] = (byte) EOLChar.charAt(k);
+ }
+ i += k-1;
+ j += k-1;
+ }
+ }
+ // New line character varies with platform,
+ // ex. For windows '\r\n', for linux '\n'.
+ // While replacing space from serialized object stream, the length
+ // of EOL character will affect the expected string as well.
+ expectedString = newExpectedString;
+
+ // De-serialize TextField object stream.
+ ByteArrayInputStream bais = new ByteArrayInputStream(streamedBytes);
+ ObjectInput inStream = new ObjectInputStream(bais);
+ textField = (TextField) inStream.readObject();
+ } catch (Exception ex) {
+ // Serialization or De-serialization failed.
+ // Create textField with empty string to show failure.
+ ex.printStackTrace();
+ textField = new TextField();
+ }
+
+ checkTest();
+ mainFrame.remove(textFieldToSerialize);
+ }
+
+ private void checkTest() {
+ if (!textField.getText().equals(expectedString)) {
+ testFailMessage.append("TestFail line : ");
+ testFailMessage.append(Thread.currentThread().getStackTrace()[2].
+ getLineNumber());
+ testFailMessage.append(" TextField.getText() : \"");
+ testFailMessage.append(textField.getText());
+ testFailMessage.append("\" does not match expected string : \"");
+ testFailMessage.append(expectedString).append("\"");
+ testFailMessage.append(System.getProperty("line.separator"));
+ testFailCount++;
+ isTestFail = true;
+ }
+ }
+
+ private void checkFailures() {
+ if (isTestFail) {
+ testFailMessage.insert(0, "Test Fail count : " + testFailCount
+ + System.getProperty("line.separator"));
+ dispose();
+ throw new RuntimeException(testFailMessage.toString());
+ }
+ }
+
+ private void dispose() {
+ if (mainFrame != null) {
+ mainFrame.dispose();
+ }
+ }
+
+ public static void main(String[] args) {
+ EOLTest testEOL = new EOLTest();
+ testEOL.testConstructor1();
+ testEOL.testConstructor2();
+ testEOL.testConstructor3();
+ testEOL.testSetText();
+ testEOL.testDeserialization();
+ testEOL.checkFailures();
+ testEOL.dispose();
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TextField/TextFieldEditing/TextFieldEditing.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+/*
+ @test
+ @bug 8060137
+ @library ../../regtesthelpers
+ @build Util
+ @summary Test TextField setText API
+ @run main TextFieldEditing
+ */
+
+import java.awt.Frame;
+import java.awt.Robot;
+import java.awt.TextField;
+import java.awt.AWTException;
+import java.awt.event.KeyEvent;
+import test.java.awt.regtesthelpers.Util;
+
+public class TextFieldEditing {
+
+ final static Robot robot = Util.createRobot();
+ private int testFailCount;
+ private boolean isTestFail;
+ private StringBuilder testFailMessage;
+
+ private Frame mainFrame;
+ private TextField textField;
+
+ private TextFieldEditing() {
+ testFailMessage = new StringBuilder();
+ mainFrame = new Frame();
+ mainFrame.setSize(200, 200);
+
+ textField = new TextField();
+ mainFrame.add(textField);
+ mainFrame.setVisible(true);
+ }
+
+ private void dispose() {
+ if (mainFrame != null) {
+ mainFrame.dispose();
+ }
+ }
+
+ public static void main(String[] s) {
+ TextFieldEditing textField = new TextFieldEditing();
+ textField.testSetText();
+ textField.checkFailures();
+ textField.dispose();
+ }
+
+ private void testSetText() {
+ textField.setText(null);
+ textField.requestFocus();
+ Util.clickOnComp(textField, robot);
+ Util.waitForIdle(robot);
+ robot.keyPress(KeyEvent.VK_A);
+ robot.delay(5);
+ robot.keyRelease(KeyEvent.VK_A);
+ Util.waitForIdle(robot);
+ textField.setText(null);
+ checkTest("");
+ textField.setText("CaseSensitive");
+ checkTest("CaseSensitive");
+ textField.setText("caseSensitive");
+ checkTest("caseSensitive");
+ }
+
+ private void checkTest(String str) {
+ if (str != null && !str.equals(textField.getText())) {
+ testFailMessage.append("TestFail line : ");
+ testFailMessage.append(Thread.currentThread().getStackTrace()[2].
+ getLineNumber());
+ testFailMessage.append(" TextField string : \"");
+ testFailMessage.append(textField.getText());
+ testFailMessage.append("\" does not match expected string : \"");
+ testFailMessage.append(str).append("\"");
+ testFailMessage.append(System.getProperty("line.separator"));
+ testFailCount++;
+ isTestFail = true;
+ }
+ }
+
+ private void checkFailures() {
+ if (isTestFail) {
+ testFailMessage.insert(0, "Test Fail count : " + testFailCount
+ + System.getProperty("line.separator"));
+ dispose();
+ throw new RuntimeException(testFailMessage.toString());
+ }
+ }
+}
--- a/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/ActionCommand/ActionCommand.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -59,8 +59,11 @@
"and rerun test.");
} else if (System.getProperty("os.name").toLowerCase().startsWith("mac")){
isMacOS = true;
+ } else if (SystemTrayIconHelper.isOel7()) {
+ System.out.println("OEL 7 doesn't support double click in " +
+ "systray. Skipped");
+ return;
}
-
new ActionCommand().doTest();
}
}
--- a/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/ActionEventMask/ActionEventMask.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -66,6 +66,10 @@
} else {
if (System.getProperty("os.name").toLowerCase().startsWith("mac")) {
isMacOS = true;
+ } else if (SystemTrayIconHelper.isOel7()) {
+ System.out.println("OEL 7 doesn't support double click in " +
+ "systray. Skipped");
+ return;
}
new ActionEventMask().doTest();
}
--- a/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/ModalityTest/ModalityTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -35,6 +35,7 @@
*/
public class ModalityTest {
+ private static boolean isOEL7;
TrayIcon icon;
ExtendedRobot robot;
Dialog d;
@@ -80,7 +81,7 @@
"\"Always show all icons and notifications on the taskbar\" true " +
"to avoid this problem. Or change behavior only for Java SE tray " +
"icon and rerun test.");
-
+ isOEL7 = SystemTrayIconHelper.isOel7();
new ModalityTest().doTest();
}
}
@@ -225,6 +226,12 @@
Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
if (iconPosition == null)
throw new RuntimeException("Unable to find the icon location!");
+ if (isOEL7) {
+ // close tray
+ robot.mouseMove(100,100);
+ robot.click(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle(2000);
+ }
if (! d.isVisible())
throw new RuntimeException("FAIL: The modal dialog is not yet visible");
@@ -232,27 +239,35 @@
robot.mouseMove(iconPosition.x, iconPosition.y);
robot.waitForIdle(2000);
- SystemTrayIconHelper.doubleClick(robot);
+ if(!isOEL7) {
+ SystemTrayIconHelper.doubleClick(robot);
- if (! actionPerformed) {
- synchronized (actionLock) {
- try {
- actionLock.wait(3000);
- } catch (Exception e) {
+ if (!actionPerformed) {
+ synchronized (actionLock) {
+ try {
+ actionLock.wait(3000);
+ } catch (Exception e) {
+ }
}
}
+ if (!actionPerformed)
+ throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
}
- if (! actionPerformed)
- throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
for (int i = 0; i < buttonTypes.length; i++) {
mousePressed = false;
- robot.mousePress(buttonTypes[i]);
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mousePress(buttonTypes[i]);
+ }
if (! mousePressed) {
synchronized (pressLock) {
try {
- pressLock.wait(3000);
+ pressLock.wait(6000);
} catch (Exception e) {
}
}
@@ -264,12 +279,18 @@
mouseReleased = false;
mouseClicked = false;
- robot.mouseRelease(buttonTypes[i]);
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mouseRelease(buttonTypes[i]);
+ }
if (! mouseReleased) {
synchronized (releaseLock) {
try {
- releaseLock.wait(3000);
+ releaseLock.wait(6000);
} catch (Exception e) {
}
}
@@ -281,7 +302,7 @@
if (! mouseClicked) {
synchronized (clickLock) {
try {
- clickLock.wait(3000);
+ clickLock.wait(6000);
} catch (Exception e) {
}
}
@@ -290,13 +311,14 @@
throw new RuntimeException("FAIL: mouseClicked not triggered when " +
buttonNames[i] + " pressed & released");
}
+ if (!isOEL7) {
+ mouseMoved = false;
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.glide(iconPosition.x + 100, iconPosition.y);
- mouseMoved = false;
- robot.mouseMove(iconPosition.x, iconPosition.y);
- robot.glide(iconPosition.x + 100, iconPosition.y);
-
- if (! mouseMoved)
- if (! SystemTrayIconHelper.skip(0) )
- throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ if (!mouseMoved)
+ if (!SystemTrayIconHelper.skip(0))
+ throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ }
}
}
--- a/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/MouseEventMask/MouseEventMaskTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -71,6 +71,8 @@
"\"Always show all icons and notifications on the taskbar\" true " +
"to avoid this problem. Or change behavior only for Java SE tray " +
"icon and rerun test.");
+ } else if (SystemTrayIconHelper.isOel7()) {
+ return;
}
new MouseEventMaskTest().doTest();
}
--- a/jdk/test/java/awt/TrayIcon/MouseMovedTest/MouseMovedTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/MouseMovedTest/MouseMovedTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -31,7 +31,7 @@
* @summary Check for mouseMoved event for java.awt.TrayIcon
* @author Dmitriy Ermashov (dmitriy.ermashov@oracle.com)
* @library ../../../../lib/testlibrary
- * @build ExtendedRobot
+ * @build ExtendedRobot SystemTrayIconHelper
* @run main MouseMovedTest
*/
@@ -39,6 +39,14 @@
static volatile boolean moved;
public static void main(String[] args) throws Exception {
+ if (!SystemTray.isSupported()) {
+ return;
+ }
+
+ if (SystemTrayIconHelper.isOel7()) {
+ return;
+ }
+
moved = false;
TrayIcon icon = new TrayIcon(new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB), "Test icon");
--- a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/FunctionalityCheck.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -51,6 +51,7 @@
boolean mouseReleased = false;
boolean mouseClicked = false;
boolean mouseMoved = false;
+ static boolean isOEL7;
static final int[] buttonTypes = {
InputEvent.BUTTON1_MASK,
@@ -69,6 +70,7 @@
System.out.println("SystemTray not supported on the platform under test. " +
"Marking the test passed");
} else {
+ isOEL7 = SystemTrayIconHelper.isOel7();
new FunctionalityCheck().doTest();
}
}
@@ -188,31 +190,44 @@
Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
if (iconPosition == null)
throw new RuntimeException("Unable to find the icon location!");
+ if (isOEL7) {
+ // close tray
+ robot.mouseMove(100,100);
+ robot.click(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle(2000);
+ }
robot.mouseMove(iconPosition.x, iconPosition.y);
- robot.waitForIdle(2000);
-
- SystemTrayIconHelper.doubleClick(robot);
+ robot.waitForIdle();
+ if(!isOEL7) {
+ SystemTrayIconHelper.doubleClick(robot);
- if (! actionPerformed) {
- synchronized (actionLock) {
- try {
- actionLock.wait(3000);
- } catch (Exception e) {
+ if (!actionPerformed) {
+ synchronized (actionLock) {
+ try {
+ actionLock.wait(3000);
+ } catch (Exception e) {
+ }
}
}
+ if (!actionPerformed)
+ throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
}
- if (! actionPerformed)
- throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
for (int i = 0; i < buttonTypes.length; i++) {
mousePressed = false;
- robot.mousePress(buttonTypes[i]);
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mousePress(buttonTypes[i]);
+ }
if (! mousePressed) {
synchronized (pressLock) {
try {
- pressLock.wait(3000);
+ pressLock.wait(6000);
} catch (Exception e) {
}
}
@@ -224,12 +239,17 @@
mouseReleased = false;
mouseClicked = false;
- robot.mouseRelease(buttonTypes[i]);
-
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mouseRelease(buttonTypes[i]);
+ }
if (! mouseReleased) {
synchronized (releaseLock) {
try {
- releaseLock.wait(3000);
+ releaseLock.wait(6000);
} catch (Exception e) {
}
}
@@ -242,7 +262,7 @@
if (! mouseClicked) {
synchronized (clickLock) {
try {
- clickLock.wait(3000);
+ clickLock.wait(6000);
} catch (Exception e) {
}
}
@@ -251,13 +271,14 @@
throw new RuntimeException("FAIL: mouseClicked not triggered when " +
buttonNames[i] + " pressed & released");
}
+ if(!isOEL7) {
+ mouseMoved = false;
+ robot.mouseMove(iconPosition.x + 100, iconPosition.y);
+ robot.glide(iconPosition.x, iconPosition.y);
- mouseMoved = false;
- robot.mouseMove(iconPosition.x + 100, iconPosition.y);
- robot.glide(iconPosition.x, iconPosition.y);
-
- if (! mouseMoved)
- if (! SystemTrayIconHelper.skip(0) )
- throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ if (!mouseMoved)
+ if (!SystemTrayIconHelper.skip(0))
+ throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ }
}
}
--- a/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/tray.policy Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/SecurityCheck/FunctionalityCheck/tray.policy Wed Jan 06 14:54:24 2016 +0000
@@ -5,6 +5,7 @@
permission java.util.PropertyPermission "resultsDir", "read";
permission java.util.PropertyPermission "user.home", "read";
permission java.util.PropertyPermission "os.name", "read";
+ permission java.util.PropertyPermission "os.version", "read";
permission java.awt.AWTPermission "accessEventQueue";
permission java.lang.RuntimePermission "setIO";
permission java.lang.RuntimePermission "accessDeclaredMembers";
@@ -17,5 +18,6 @@
permission java.util.PropertyPermission "java.class.path", "read";
permission java.awt.AWTPermission "readDisplayPixels";
permission java.awt.AWTPermission "watchMousePointer";
+
};
--- a/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/SystemTrayIconHelper.java Wed Jan 06 14:54:24 2016 +0000
@@ -66,7 +66,9 @@
for (int x = (int) (screenSize.getWidth()-width); x > 0; x--) {
for (int y = (int) (screenSize.getHeight()-height); y > (screenSize.getHeight()-50); y--) {
if (imagesEquals(((BufferedImage)icon.getImage()).getSubimage(0, 0, width, height), screen.getSubimage(x, y, width, height))) {
- return new Point(x+5, y+5);
+ Point point = new Point(x + 5, y + 5);
+ System.out.println("Icon location " + point);
+ return point;
}
}
}
@@ -91,6 +93,7 @@
point2d = (Point2D)m_getLocation.invoke(peer, new Object[]{model});
Point po = new Point((int)(point2d.getX()), (int)(point2d.getY()));
po.translate(10, -5);
+ System.out.println("Icon location " + po);
return po;
}catch(Exception e) {
e.printStackTrace();
@@ -101,12 +104,15 @@
// sun.awt.X11.XTrayIconPeer
Field f_peer = getField(java.awt.TrayIcon.class, "peer");
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+
Object peer = f_peer.get(icon);
Method m_getLOS = peer.getClass().getDeclaredMethod(
"getLocationOnScreen", new Class[]{});
m_getLOS.setAccessible(true);
Point point = (Point)m_getLOS.invoke(peer, new Object[]{});
point.translate(5, 5);
+ System.out.println("Icon location " + point);
return point;
} catch (Exception e) {
e.printStackTrace();
@@ -169,4 +175,38 @@
}
return false;
}
+
+ public static boolean openTrayIfNeeded(Robot robot) {
+ String sysv = System.getProperty("os.version");
+ System.out.println("System version is " + sysv);
+ //Additional step to raise the system try in Gnome 3 in OEL 7
+ if(isOel7()) {
+ System.out.println("OEL 7 detected");
+ GraphicsConfiguration gc = GraphicsEnvironment.
+ getLocalGraphicsEnvironment().getDefaultScreenDevice().
+ getDefaultConfiguration();
+ Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc);
+ if(insets.bottom > 0) {
+ Dimension screenSize = Toolkit.getDefaultToolkit()
+ .getScreenSize();
+ robot.mouseMove(screenSize.width - insets.bottom / 2,
+ screenSize.height - insets.bottom / 2);
+ robot.delay(50);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.delay(50);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle();
+ robot.delay(1000);
+ System.out.println("Tray is opened");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isOel7() {
+ return System.getProperty("os.name").toLowerCase()
+ .contains("linux") && System.getProperty("os.version")
+ .toLowerCase().contains("el7");
+ }
}
--- a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -121,6 +121,12 @@
};
}
+ if (SystemTrayIconHelper.isOel7()) {
+ System.out.println("OEL 7 doesn't support click modifiers in " +
+ "systray. Skipped");
+ return;
+ }
+
new TrayIconEventModifiersTest().doTest();
}
}
--- a/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEvents/TrayIconEventsTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -37,6 +37,7 @@
public class TrayIconEventsTest {
+ private static boolean isOEL7;
TrayIcon icon;
ExtendedRobot robot;
@@ -77,6 +78,7 @@
"\"Always show all icons and notifications on the taskbar\" true " +
"to avoid this problem. Or change behavior only for Java SE " +
"tray icon.");
+ isOEL7 = SystemTrayIconHelper.isOel7();
new TrayIconEventsTest().doTest();
}
}
@@ -195,31 +197,44 @@
Point iconPosition = SystemTrayIconHelper.getTrayIconLocation(icon);
if (iconPosition == null)
throw new RuntimeException("Unable to find the icon location!");
+ if (isOEL7) {
+ // close tray
+ robot.mouseMove(100,100);
+ robot.click(InputEvent.BUTTON1_MASK);
+ robot.waitForIdle(2000);
+ }
robot.mouseMove(iconPosition.x, iconPosition.y);
- robot.waitForIdle(2000);
-
- SystemTrayIconHelper.doubleClick(robot);
+ robot.waitForIdle();
+ if(!isOEL7) {
+ SystemTrayIconHelper.doubleClick(robot);
- if (! actionPerformed) {
- synchronized (actionLock) {
- try {
- actionLock.wait(10000);
- } catch (Exception e) {
+ if (!actionPerformed) {
+ synchronized (actionLock) {
+ try {
+ actionLock.wait(10000);
+ } catch (Exception e) {
+ }
}
}
+ if (!actionPerformed)
+ throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
}
- if (! actionPerformed)
- throw new RuntimeException("FAIL: ActionEvent not triggered when TrayIcon is double clicked");
for (int i = 0; i < buttonTypes.length; i++) {
mousePressed = false;
- robot.mousePress(buttonTypes[i]);
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mousePress(buttonTypes[i]);
+ }
if (! mousePressed) {
synchronized (pressLock) {
try {
- pressLock.wait(3000);
+ pressLock.wait(6000);
} catch (Exception e) {
}
}
@@ -231,12 +246,18 @@
mouseReleased = false;
mouseClicked = false;
- robot.mouseRelease(buttonTypes[i]);
+ if(isOEL7) {
+ SystemTrayIconHelper.openTrayIfNeeded(robot);
+ robot.mouseMove(iconPosition.x, iconPosition.y);
+ robot.click(buttonTypes[i]);
+ } else {
+ robot.mouseRelease(buttonTypes[i]);
+ }
if (! mouseReleased) {
synchronized (releaseLock) {
try {
- releaseLock.wait(3000);
+ releaseLock.wait(6000);
} catch (Exception e) {
}
}
@@ -248,7 +269,7 @@
if (! mouseClicked) {
synchronized (clickLock) {
try {
- clickLock.wait(3000);
+ clickLock.wait(6000);
} catch (Exception e) {
}
}
@@ -258,12 +279,14 @@
buttonNames[i] + " pressed & released");
}
- mouseMoved = false;
- robot.mouseMove(iconPosition.x + 100, iconPosition.y);
- robot.glide(iconPosition.x, iconPosition.y);
+ if (!isOEL7) {
+ mouseMoved = false;
+ robot.mouseMove(iconPosition.x + 100, iconPosition.y);
+ robot.glide(iconPosition.x, iconPosition.y);
- if (! mouseMoved)
- if (! SystemTrayIconHelper.skip(0) )
- throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ if (!mouseMoved)
+ if (!SystemTrayIconHelper.skip(0))
+ throw new RuntimeException("FAIL: mouseMoved not triggered even when mouse moved over the icon");
+ }
}
}
--- a/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/TrayIconMouseTest/TrayIconMouseTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -66,6 +66,10 @@
} else {
if (System.getProperty("os.name").toLowerCase().startsWith("mac")) {
isMacOS = true;
+ } else if (SystemTrayIconHelper.isOel7()) {
+ System.out.println("OEL 7 doesn't support double click in " +
+ "systray. Skipped");
+ return;
}
new TrayIconMouseTest().doTest();
}
@@ -108,7 +112,7 @@
for (int i = 0; i < buttonTypes.length; i++) {
actionPerformed = false;
robot.click(buttonTypes[i]);
- robot.waitForIdle(2000);
+ robot.waitForIdle(6000);
if (isMacOS && actionPerformed && i == 2) {
@@ -155,7 +159,7 @@
if (! actionPerformed) {
synchronized (actionLock) {
try {
- actionLock.wait(3000);
+ actionLock.wait(6000);
} catch (Exception e) {
}
}
--- a/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/awt/TrayIcon/TrayIconPopup/TrayIconPopupTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -127,7 +127,7 @@
robot.mousePress(InputEvent.BUTTON3_MASK);
robot.delay(50);
robot.mouseRelease(InputEvent.BUTTON3_MASK);
- robot.delay(1000);
+ robot.delay(6000);
robot.mouseMove(window.getLocation().x + 10, window.getLocation().y + 10);
robot.mousePress(InputEvent.BUTTON3_MASK);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/font/GlyphVector/TestStandardGlyphVectorBug.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,58 @@
+/*
+ * 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.awt.Font;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+/**
+ * @test
+ * @bug 7160052
+ * @run main TestStandardGlyphVectorBug
+ * @summary GlyphVector.setGlyphPosition should not throw an exception on valid input
+ */
+public class TestStandardGlyphVectorBug
+{
+ public static void main(String[] args)
+ {
+ Font defaultFont = new Font(null);
+ FontRenderContext defaultFrc = new FontRenderContext(new AffineTransform(),
+ true, true);
+ GlyphVector gv = defaultFont.createGlyphVector(defaultFrc, "test");
+
+ //this causes the bounds to be cached
+ //which is necessary to trigger the bug
+ gv.getGlyphLogicalBounds(0);
+
+ //this correctly gets the position of the overall advance
+ Point2D glyphPosition = gv.getGlyphPosition(gv.getNumGlyphs());
+
+ // this sets the position of the overall advance,
+ // but also incorrectly tries to clear the bounds cache
+ // of a specific glyph indexed by the glyphIndex parameter
+ // even if the glyphIndex represents the overall advance
+ // (i.e. if glyphIndex == getNumGlyphs())
+ gv.setGlyphPosition(gv.getNumGlyphs(), glyphPosition);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/VolatileImage/VolatileImageBug.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,52 @@
+/*
+ * 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.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.image.VolatileImage;
+
+/**
+ * @test
+ * @bug 8140530
+ * @run main VolatileImageBug
+ * @summary Creating volatileimage(0,0) should throw IAE
+ */
+public class VolatileImageBug {
+ public static void main(String[] args) {
+
+ boolean iaeThrown = false;
+ GraphicsEnvironment ge = GraphicsEnvironment.
+ getLocalGraphicsEnvironment();
+ GraphicsConfiguration gc = ge.getDefaultScreenDevice().
+ getDefaultConfiguration();
+ try {
+ VolatileImage volatileImage = gc.createCompatibleVolatileImage(0, 0);
+ } catch (IllegalArgumentException iae) {
+ iaeThrown = true;
+ }
+ if (!iaeThrown) {
+ throw new RuntimeException ("IllegalArgumentException not thrown " +
+ "for createCompatibleVolatileImage(0,0)");
+ }
+ }
+}
+
--- a/jdk/test/java/beans/EventHandler/Test6277246.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/beans/EventHandler/Test6277246.java Wed Jan 06 14:54:24 2016 +0000
@@ -39,7 +39,7 @@
Class container = Class.forName("java.lang.Class");
Class parameter = Class.forName("java.lang.String");
Method method = container.getMethod("forName", parameter);
- Object[] arglist = new Object[] {"sun.misc.BASE64Encoder"};
+ Object[] arglist = new Object[] {"sun.security.x509.X509CertInfo"};
EventHandler eh = new EventHandler(Test6277246.class, "forName", "", "forName");
Object object = eh.invoke(null, method, arglist);
throw new Error((object != null) ? "test failure" : "test error");
--- a/jdk/test/java/beans/Introspector/Test6277246.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/beans/Introspector/Test6277246.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,7 +25,7 @@
* @test
* @bug 6277246
* @summary Tests problem with java.beans use of reflection
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
* java.desktop
* @run main/othervm Test6277246
* @author Jeff Nisewanger
@@ -36,11 +36,10 @@
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.Method;
-import sun.misc.BASE64Encoder;
public class Test6277246 {
public static void main(String[] args) throws IntrospectionException {
- Class type = BASE64Encoder.class;
+ Class type = sun.security.x509.X509CertInfo.class;
System.setSecurityManager(new SecurityManager());
BeanInfo info = Introspector.getBeanInfo(type);
for (MethodDescriptor md : info.getMethodDescriptors()) {
@@ -48,7 +47,7 @@
System.out.println(method);
String name = method.getDeclaringClass().getName();
- if (name.startsWith("sun.misc.")) {
+ if (name.startsWith("sun.")) {
throw new Error("found inaccessible method");
}
}
--- a/jdk/test/java/beans/Statement/Test6224433.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/beans/Statement/Test6224433.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,7 +36,7 @@
System.setSecurityManager(new SecurityManager());
Class target = Test6224433.class;
String method = "forName";
- String[] params = {"sun.misc.BASE64Encoder"};
+ String[] params = {"sun.security.x509.X509CertInfo"};
if (null != new Expression(target, method, params).getValue())
throw new Error("failure: bug exists");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/javax_swing_JComponent.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,77 @@
+/*
+ * 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 javax.swing.JComponent;
+import javax.swing.plaf.ComponentUI;
+
+/*
+ * @test
+ * @bug 8131754
+ * @summary Tests JComponent encoding
+ */
+public final class javax_swing_JComponent extends AbstractTest<JComponent> {
+
+ public static void main(final String[] args) {
+ new javax_swing_JComponent().test(true);
+ }
+
+ protected JComponent getObject() {
+ return new SimpleJComponent();
+ }
+
+ protected JComponent getAnotherObject() {
+ return new CustomJComponent();
+ }
+
+ public static final class SimpleJComponent extends JComponent {
+
+ }
+
+ public static final class CustomJComponent extends JComponent {
+
+ public CustomJComponent() {
+ ui = new CustomUI();
+ }
+
+ @Override
+ public ComponentUI getUI() {
+ return ui;
+ }
+
+ @Override
+ public void setUI(final ComponentUI newUI) {
+ ui = newUI;
+ }
+ }
+
+ public static final class CustomUI extends ComponentUI {
+
+ public boolean getFlag() {
+ throw new Error();
+ }
+
+ public void setFlag(final boolean flag) {
+ throw new Error();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/PushbackReader/ReadCloseRaceNPE.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8143394
+ * @summary Check for NullPointerException in race between read() and close().
+ */
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.PushbackReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Supplier;
+
+public class ReadCloseRaceNPE {
+
+ private static final int BUF_SIZE = 1000;
+ private static final long TIMEOUT_MS = 3000;
+
+ private static final List<Exception> failures = new ArrayList<>();
+
+ private static void testReader(final Supplier<Reader> readerSupplier)
+ throws InterruptedException {
+ AtomicReference<Reader> readerRef =
+ new AtomicReference<>(readerSupplier.get());
+
+ AtomicBoolean isFinished = new AtomicBoolean();
+
+ Runnable readTask = () -> {
+ long startTime = System.currentTimeMillis();
+ while (System.currentTimeMillis() - startTime < TIMEOUT_MS) {
+ try {
+ readerRef.get().read();
+ } catch (Exception e) {
+ if (!(e instanceof IOException)) {
+ failures.add(e);
+ break;
+ }
+ readerRef.set(readerSupplier.get());
+ }
+ }
+ isFinished.set(true);
+ };
+
+ Runnable closeTask = () -> {
+ while (!isFinished.get()) {
+ try {
+ readerRef.get().close();
+ } catch (Exception e) {
+ if (!(e instanceof IOException)) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+
+ Thread readThread = new Thread(readTask);
+ Thread closeThread = new Thread(closeTask);
+
+ readThread.start();
+ closeThread.start();
+ readThread.join();
+ closeThread.join();
+ }
+
+ public static void main(String[] args) throws Throwable {
+ final String s = "Two riders were approaching.\\n";
+
+ Supplier<Reader> charPushbackReaderSupplier = () -> {
+ char buf[] = new char[s.length()];
+ s.getChars(0, s.length(), buf, 0);
+ CharArrayReader in = new CharArrayReader(buf);
+ return new PushbackReader(in, BUF_SIZE);
+ };
+
+ testReader(charPushbackReaderSupplier);
+
+ Supplier<Reader> stringPushbackReaderSupplier = () -> {
+ StringReader in = new StringReader(s);
+ return new PushbackReader(in, BUF_SIZE);
+ };
+
+ testReader(stringPushbackReaderSupplier);
+
+ if (!failures.isEmpty()) {
+ failures.stream().forEach((x) -> ((Exception) x).printStackTrace());
+ throw new RuntimeException("PushbackReaderNPE failed");
+ }
+ }
+}
--- a/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -49,7 +49,7 @@
/*
* @test
- * @bug 8077350 8081566 8081567 8098852
+ * @bug 8077350 8081566 8081567 8098852 8136597
* @build jdk.testlibrary.*
* @library /lib/testlibrary
* @summary Functions of ProcessHandle.Info
@@ -210,10 +210,12 @@
Assert.assertTrue(commandLine.contains(allArgs.get(i)),
"commandLine() must contain argument: " + allArgs.get(i));
}
- } else if (info.commandLine().isPresent()) {
+ } else if (info.commandLine().isPresent() &&
+ command.isPresent() &&
+ command.get().length() < info.commandLine().get().length()) {
// If we only have the commandLine() we can only do some basic checks...
String commandLine = info.commandLine().get();
- String javaExe = "java" + (Platform.isWindows() ? ".exe": "");
+ String javaExe = "java" + (Platform.isWindows() ? ".exe" : "");
int pos = commandLine.indexOf(javaExe);
Assert.assertTrue(pos > 0, "commandLine() should at least contain 'java'");
--- a/jdk/test/java/lang/StackWalker/MultiThreadStackWalk.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/StackWalker/MultiThreadStackWalk.java Wed Jan 06 14:54:24 2016 +0000
@@ -328,7 +328,7 @@
public void run() {
try {
- Env env = runTest(test, 2000, 10);
+ Env env = runTest(test, 1000, 10);
//waitWalkers(env);
checkTest(env, test);
} catch(Throwable t) {
--- a/jdk/test/java/lang/StackWalker/StackWalkTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/StackWalker/StackWalkTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -236,6 +236,8 @@
if (didWalk) {
throw new IllegalStateException("StackWalkTest already used");
}
+ // Test may run into StackOverflow when running in -Xcomp mode on deep stack
+ assert stackDepth <= 1000;
assert markAt <= stackDepth : "markAt(" + markAt + ") > stackDepth("
+ stackDepth + ")";
System.out.print("runTest(" + swOptions
@@ -297,15 +299,15 @@
// Long stack, default maxDepth
StackWalkTest swt;
swt = new StackWalkTest();
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
// Long stack, matching maxDepth
swt = new StackWalkTest(2000);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
// Long stack, maximum maxDepth
swt = new StackWalkTest(Integer.MAX_VALUE);
- swt.runTest(StackWalkTest.class, "main", 2000, 10);
+ swt.runTest(StackWalkTest.class, "main", 1000, 10);
//
// Single batch
@@ -349,7 +351,7 @@
swt.runTest(StackWalkTest.class, "main", 80, 40);
swt = new StackWalkTest(EnumSet.of(RETAIN_CLASS_REFERENCE), 50);
- swt.runTest(StackWalkTest.class, "main", 2000, 1048);
+ swt.runTest(StackWalkTest.class, "main", 1000, 524);
}
}
}
--- a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,13 +43,16 @@
import java.lang.System.LoggerFinder;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.function.Function;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.stream.Stream;
/**
* @test
- * @bug 8140364
+ * @bug 8140364 8145686
* @summary Tests default loggers returned by System.getLogger, and in
* particular the implementation of the the System.Logger method
* performed by the default binding.
@@ -59,6 +62,8 @@
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOSECURITY
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOPERMISSIONS
* @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest WITHPERMISSIONS
+ * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest WITHCUSTOMWRAPPERS
+ * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest WITHREFLECTION
* @author danielfuchs
*/
public class DefaultLoggerTest {
@@ -232,7 +237,8 @@
static final AccessSystemLogger accessSystemLogger = new AccessSystemLogger();
- static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};
+ static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS,
+ WITHCUSTOMWRAPPERS, WITHREFLECTION};
static void setSecurityManager() {
if (System.getSecurityManager() == null) {
@@ -240,12 +246,179 @@
System.setSecurityManager(new SecurityManager());
}
}
+
+ /**
+ * The CustomLoggerWrapper makes it possible to verify that classes
+ * which implements System.Logger will be skipped when looking for
+ * the calling method.
+ */
+ static class CustomLoggerWrapper implements Logger {
+
+ Logger impl;
+ public CustomLoggerWrapper(Logger logger) {
+ this.impl = Objects.requireNonNull(logger);
+ }
+
+
+ @Override
+ public String getName() {
+ return impl.getName();
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ return impl.isLoggable(level);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {
+ impl.log(level, rb, string, thrwbl);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Object... os) {
+ impl.log(level, rb, string, os);
+ }
+
+ @Override
+ public void log(Level level, Object o) {
+ impl.log(level, o);
+ }
+
+ @Override
+ public void log(Level level, String string) {
+ impl.log(level, string);
+ }
+
+ @Override
+ public void log(Level level, Supplier<String> splr) {
+ impl.log(level, splr);
+ }
+
+ @Override
+ public void log(Level level, String string, Object... os) {
+ impl.log(level, string, os);
+ }
+
+ @Override
+ public void log(Level level, String string, Throwable thrwbl) {
+ impl.log(level, string, thrwbl);
+ }
+
+ @Override
+ public void log(Level level, Supplier<String> splr, Throwable thrwbl) {
+ Logger.super.log(level, splr, thrwbl);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "(impl=" + impl + ")";
+ }
+
+ }
+
+ /**
+ * The ReflectionLoggerWrapper additionally makes it possible to verify
+ * that code which use reflection to call System.Logger will be skipped
+ * when looking for the calling method.
+ */
+ static class ReflectionLoggerWrapper implements Logger {
+
+ Logger impl;
+ public ReflectionLoggerWrapper(Logger logger) {
+ this.impl = Objects.requireNonNull(logger);
+ }
+
+ private Object invoke(Method m, Object... params) {
+ try {
+ return m.invoke(impl, params);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return impl.getName();
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ return impl.isLoggable(level);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, ResourceBundle.class, String.class, Throwable.class),
+ level, rb, string, thrwbl);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Object... os) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, ResourceBundle.class, String.class, Object[].class),
+ level, rb, string, os);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class),
+ level, string);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string, Object... os) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class, Object[].class),
+ level, string, os);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string, Throwable thrwbl) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class, Throwable.class),
+ level, string, thrwbl);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ return super.toString() + "(impl=" + impl + ")";
+ }
+
+ }
+
public static void main(String[] args) {
if (args.length == 0)
args = new String[] {
"NOSECURITY",
"NOPERMISSIONS",
- "WITHPERMISSIONS"
+ "WITHPERMISSIONS",
+ "WITHCUSTOMWRAPPERS",
+ "WITHREFLECTION"
};
// 1. Obtain destination loggers directly from the LoggerFinder
@@ -276,6 +449,31 @@
allowControl.get().set(control);
}
break;
+ case WITHCUSTOMWRAPPERS:
+ System.out.println("\n*** With Security Manager, with control permission, using custom Wrappers\n");
+ setSecurityManager();
+ final boolean previous = allowControl.get().get();
+ try {
+ allowControl.get().set(true);
+ test(CustomLoggerWrapper::new, true);
+ } finally {
+ allowControl.get().set(previous);
+ }
+ break;
+ case WITHREFLECTION:
+ System.out.println("\n*** With Security Manager,"
+ + " with control permission,"
+ + " using reflection while logging\n");
+ setSecurityManager();
+ final boolean before = allowControl.get().get();
+ try {
+ allowControl.get().set(true);
+ test(ReflectionLoggerWrapper::new, true);
+ } finally {
+ allowControl.get().set(before);
+ }
+ break;
+
default:
throw new RuntimeException("Unknown test case: " + testCase);
}
@@ -284,6 +482,10 @@
}
public static void test(boolean hasRequiredPermissions) {
+ test(Function.identity(), hasRequiredPermissions);
+ }
+
+ public static void test(Function<Logger, Logger> wrapper, boolean hasRequiredPermissions) {
ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());
final Map<Logger, String> loggerDescMap = new HashMap<>();
@@ -294,7 +496,7 @@
// - and AccessSystemLogger.getLogger("foo")
Logger sysLogger1 = null;
try {
- sysLogger1 = accessSystemLogger.getLogger("foo");
+ sysLogger1 = wrapper.apply(accessSystemLogger.getLogger("foo"));
loggerDescMap.put(sysLogger1, "AccessSystemLogger.getLogger(\"foo\")");
} catch (AccessControlException acx) {
if (hasRequiredPermissions) {
@@ -306,7 +508,7 @@
throw new RuntimeException("unexpected exception: " + acx, acx);
}
- Logger appLogger1 = System.getLogger("foo");
+ Logger appLogger1 = wrapper.apply(System.getLogger("foo"));
loggerDescMap.put(appLogger1, "System.getLogger(\"foo\");");
if (appLogger1 == sysLogger1) {
@@ -316,13 +518,13 @@
// 2. Test loggers returned by:
// - System.getLogger(\"foo\", loggerBundle)
// - and AccessSystemLogger.getLogger(\"foo\", loggerBundle)
- Logger appLogger2 =
- System.getLogger("foo", loggerBundle);
+ Logger appLogger2 = wrapper.apply(
+ System.getLogger("foo", loggerBundle));
loggerDescMap.put(appLogger2, "System.getLogger(\"foo\", loggerBundle)");
Logger sysLogger2 = null;
try {
- sysLogger2 = accessSystemLogger.getLogger("foo", loggerBundle);
+ sysLogger2 = wrapper.apply(accessSystemLogger.getLogger("foo", loggerBundle));
loggerDescMap.put(sysLogger2, "AccessSystemLogger.getLogger(\"foo\", loggerBundle)");
} catch (AccessControlException acx) {
if (hasRequiredPermissions) {
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,17 +44,21 @@
import java.lang.System.LoggerFinder;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
import jdk.internal.logger.DefaultLoggerFinder;
import jdk.internal.logger.SimpleConsoleLogger;
import sun.util.logging.PlatformLogger;
/**
* @test
- * @bug 8140364
+ * @bug 8140364 8145686
* @summary JDK implementation specific unit test for the base DefaultLoggerFinder.
* Tests the behavior of DefaultLoggerFinder and SimpleConsoleLogger
* implementation.
@@ -65,6 +69,8 @@
* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest NOSECURITY
* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest NOPERMISSIONS
* @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHPERMISSIONS
+ * @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHCUSTOMWRAPPERS
+ * @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseDefaultLoggerFinderTest WITHREFLECTION
* @author danielfuchs
*/
public class BaseDefaultLoggerFinderTest {
@@ -172,7 +178,8 @@
}
- static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};
+ static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS,
+ WITHCUSTOMWRAPPERS, WITHREFLECTION};
static void setSecurityManager() {
if (System.getSecurityManager() == null) {
@@ -261,12 +268,173 @@
return b.append(name).append("=").append(value).append('\n');
}
+ static class CustomLoggerWrapper implements Logger {
+
+ Logger impl;
+ public CustomLoggerWrapper(Logger logger) {
+ this.impl = Objects.requireNonNull(logger);
+ }
+
+
+ @Override
+ public String getName() {
+ return impl.getName();
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ return impl.isLoggable(level);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {
+ impl.log(level, rb, string, thrwbl);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Object... os) {
+ impl.log(level, rb, string, os);
+ }
+
+ @Override
+ public void log(Level level, Object o) {
+ impl.log(level, o);
+ }
+
+ @Override
+ public void log(Level level, String string) {
+ impl.log(level, string);
+ }
+
+ @Override
+ public void log(Level level, Supplier<String> splr) {
+ impl.log(level, splr);
+ }
+
+ @Override
+ public void log(Level level, String string, Object... os) {
+ impl.log(level, string, os);
+ }
+
+ @Override
+ public void log(Level level, String string, Throwable thrwbl) {
+ impl.log(level, string, thrwbl);
+ }
+
+ @Override
+ public void log(Level level, Supplier<String> splr, Throwable thrwbl) {
+ Logger.super.log(level, splr, thrwbl);
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + "(impl=" + impl + ")";
+ }
+
+ }
+ /**
+ * The ReflectionLoggerWrapper additionally makes it possible to verify
+ * that code which use reflection to call System.Logger will be skipped
+ * when looking for the calling method.
+ */
+ static class ReflectionLoggerWrapper implements Logger {
+
+ Logger impl;
+ public ReflectionLoggerWrapper(Logger logger) {
+ this.impl = Objects.requireNonNull(logger);
+ }
+
+ private Object invoke(Method m, Object... params) {
+ try {
+ return m.invoke(impl, params);
+ } catch (IllegalAccessException | IllegalArgumentException
+ | InvocationTargetException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return impl.getName();
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ return impl.isLoggable(level);
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Throwable thrwbl) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, ResourceBundle.class, String.class, Throwable.class),
+ level, rb, string, thrwbl);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, ResourceBundle rb, String string, Object... os) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, ResourceBundle.class, String.class, Object[].class),
+ level, rb, string, os);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class),
+ level, string);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string, Object... os) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class, Object[].class),
+ level, string, os);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void log(Level level, String string, Throwable thrwbl) {
+ try {
+ invoke(System.Logger.class.getMethod(
+ "log", Level.class, String.class, Throwable.class),
+ level, string, thrwbl);
+ } catch (NoSuchMethodException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+
+ @Override
+ public String toString() {
+ return super.toString() + "(impl=" + impl + ")";
+ }
+
+ }
+
+
public static void main(String[] args) {
if (args.length == 0) {
args = new String[] {
//"NOSECURITY",
"NOPERMISSIONS",
- "WITHPERMISSIONS"
+ "WITHPERMISSIONS",
+ "WITHCUSTOMWRAPPERS",
+ "WITHREFLECTION"
};
}
Locale.setDefault(Locale.ENGLISH);
@@ -355,6 +523,40 @@
allowControl.get().set(control);
}
break;
+ case WITHCUSTOMWRAPPERS:
+ System.out.println("\n*** With Security Manager, with control permission and custom Wrapper\n");
+ System.out.println(TestLoggerFinder.conf.get());
+ setSecurityManager();
+ final boolean previous = allowControl.get().get();
+ try {
+ allowControl.get().set(true);
+ provider = getLoggerFinder(expectedClass);
+ if (!provider.getClass().getName().equals("BaseDefaultLoggerFinderTest$BaseLoggerFinder")) {
+ throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());
+ }
+ test(provider, CustomLoggerWrapper::new, true);
+ } finally {
+ allowControl.get().set(previous);
+ }
+ break;
+ case WITHREFLECTION:
+ System.out.println("\n*** With Security Manager,"
+ + " with control permission,"
+ + " using reflection while logging\n");
+ System.out.println(TestLoggerFinder.conf.get());
+ setSecurityManager();
+ final boolean before = allowControl.get().get();
+ try {
+ allowControl.get().set(true);
+ provider = getLoggerFinder(expectedClass);
+ if (!provider.getClass().getName().equals("BaseDefaultLoggerFinderTest$BaseLoggerFinder")) {
+ throw new RuntimeException("Unexpected provider: " + provider.getClass().getName());
+ }
+ test(provider, ReflectionLoggerWrapper::new, true);
+ } finally {
+ allowControl.get().set(before);
+ }
+ break;
default:
throw new RuntimeException("Unknown test case: " + testCase);
}
@@ -363,17 +565,21 @@
}
public static void test(TestLoggerFinder provider, boolean hasRequiredPermissions) {
+ test(provider, Function.identity(), hasRequiredPermissions);
+ }
+
+ public static void test(TestLoggerFinder provider, Function<Logger, Logger> wrapper, boolean hasRequiredPermissions) {
ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());
final Map<Logger, String> loggerDescMap = new HashMap<>();
- System.Logger sysLogger = accessSystemLogger.getLogger("foo");
+ System.Logger sysLogger = wrapper.apply(accessSystemLogger.getLogger("foo"));
loggerDescMap.put(sysLogger, "accessSystemLogger.getLogger(\"foo\")");
- System.Logger localizedSysLogger = accessSystemLogger.getLogger("fox", loggerBundle);
+ System.Logger localizedSysLogger = wrapper.apply(accessSystemLogger.getLogger("fox", loggerBundle));
loggerDescMap.put(localizedSysLogger, "accessSystemLogger.getLogger(\"fox\", loggerBundle)");
- System.Logger appLogger = System.getLogger("bar");
+ System.Logger appLogger = wrapper.apply(System.getLogger("bar"));
loggerDescMap.put(appLogger,"System.getLogger(\"bar\")");
- System.Logger localizedAppLogger = System.getLogger("baz", loggerBundle);
+ System.Logger localizedAppLogger = wrapper.apply(System.getLogger("baz", loggerBundle));
loggerDescMap.put(localizedAppLogger,"System.getLogger(\"baz\", loggerBundle)");
testLogger(provider, loggerDescMap, "foo", null, sysLogger, accessSystemLogger.getClass());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/Thread/ITLConstructor.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary Basic test for Thread(ThreadGroup,Runnable,String,long,boolean)
+ */
+
+public class ITLConstructor {
+ static InheritableThreadLocal<Integer> n = new InheritableThreadLocal<>() {
+ protected Integer initialValue() {
+ return 0;
+ }
+
+ protected Integer childValue(Integer parentValue) {
+ return parentValue + 1;
+ }
+ };
+
+ static final int CHILD_THREAD_COUNT = 10;
+
+ public static void main(String args[]) throws Exception {
+ test(true);
+ test(false);
+ }
+
+ static void test(boolean inherit) throws Exception {
+ // concurrent access to separate indexes is ok
+ int[] x = new int[CHILD_THREAD_COUNT];
+ Thread child = new Thread(Thread.currentThread().getThreadGroup(),
+ new AnotherRunnable(0, x, inherit),
+ "ITLConstructor-thread-"+(0),
+ 0,
+ inherit);
+ child.start();
+ child.join(); // waits for *all* threads to complete
+
+ // Check results
+ for(int i=0; i<CHILD_THREAD_COUNT; i++) {
+ int expectedValue = 1;
+ if (inherit)
+ expectedValue = i+1;
+
+ if (x[i] != expectedValue)
+ throw (new Exception("Got x[" + i + "] = " + x[i]
+ + ", expected: " + expectedValue));
+ }
+ }
+
+ static class AnotherRunnable implements Runnable {
+ final int threadId;
+ final int[] x;
+ final boolean inherit;
+ AnotherRunnable(int threadId, int[] x, boolean inherit) {
+ this.threadId = threadId;
+ this.x = x;
+ this.inherit = inherit;
+ }
+
+ public void run() {
+ int itlValue = n.get();
+
+ if (threadId < CHILD_THREAD_COUNT-1) {
+ Thread child = new Thread(Thread.currentThread().getThreadGroup(),
+ new AnotherRunnable(threadId+1, x, inherit),
+ "ITLConstructor-thread-" + (threadId+1),
+ 0,
+ inherit);
+ child.start();
+ try {
+ child.join();
+ } catch(InterruptedException e) {
+ throw(new RuntimeException("Interrupted", e));
+ }
+ }
+
+ x[threadId] = itlValue+1;
+ }
+ }
+}
--- a/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/annotation/TypeAnnotationReflection.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8004698 8007073 8022343 8054304 8058595
+ * @bug 8004698 8007073 8022343 8054304 8057804 8058595
* @summary Unit test for type annotations
*/
@@ -358,6 +358,31 @@
check(annos.length == 2);
check(((TypeAnno)annos[0]).value().equals("I1"));
check(args[0].getAnnotation(TypeAnno2.class).value().equals("I2"));
+
+ // check type args
+ Field f = TestParameterizedType.class.getDeclaredField("theField");
+ AnnotatedParameterizedType fType = (AnnotatedParameterizedType)f.getAnnotatedType();
+ args = fType.getAnnotatedActualTypeArguments();
+ check(args.length == 1);
+ annos = args[0].getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno2)annos[0]).value().equals("Map Arg"));
+ check(args[0].getAnnotation(TypeAnno2.class).value().equals("Map Arg"));
+
+ // check outer type type args
+ fType = (AnnotatedParameterizedType)fType.getAnnotatedOwnerType();
+ args = fType.getAnnotatedActualTypeArguments();
+ check(args.length == 1);
+ annos = args[0].getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno2)annos[0]).value().equals("String Arg"));
+ check(args[0].getAnnotation(TypeAnno2.class).value().equals("String Arg"));
+
+ // check outer type normal type annotations
+ annos = fType.getAnnotations();
+ check(annos.length == 1);
+ check(((TypeAnno)annos[0]).value().equals("FieldOuter"));
+ check(fType.getAnnotation(TypeAnno.class).value().equals("FieldOuter"));
}
private static void testWildcardType() throws Exception {
@@ -563,9 +588,12 @@
abstract class TestParameterizedType implements @TypeAnno("M") Map<@TypeAnno("S")String, @TypeAnno("I") @TypeAnno2("I2")Integer> {
public ParameterizedOuter<String>.ParameterizedInner<Integer> foo() {return null;}
public @TypeAnno("O") ParameterizedOuter<@TypeAnno("S1") @TypeAnno2("S2") String>.
- @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
+ @TypeAnno("I") ParameterizedInner<@TypeAnno("I1") @TypeAnno2("I2")Integer> foo2() {
return null;
}
+
+ public @TypeAnno("FieldOuter") ParameterizedOuter<@TypeAnno2("String Arg") String>.
+ @TypeAnno("FieldInner")ParameterizedInner<@TypeAnno2("Map Arg")Map> theField;
}
class ParameterizedOuter <T> {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/annotation/typeAnnotations/GetAnnotatedOwnerType.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,282 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8058595
+ * @summary Test that AnnotatedType.getAnnotatedOwnerType() works as expected
+ *
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.Asserts
+ * @run main GetAnnotatedOwnerType
+ */
+
+import java.lang.annotation.*;
+import java.lang.reflect.*;
+
+import jdk.testlibrary.Asserts;
+
+public class GetAnnotatedOwnerType<Dummy> {
+ public @TA("generic") GetAnnotatedOwnerType<String> . @TB("generic") Nested<Integer> genericField;
+ public @TA("raw") GetAnnotatedOwnerType . @TB("raw") Nested rawField;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("non-generic") Inner nonGeneric;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("generic") InnerGeneric<String> innerGeneric;
+ public @TA("non-generic") GetAnnotatedOwnerTypeAuxilliary . @TB("raw") InnerGeneric innerRaw;
+ public Object anonymous = new Object() {};
+ public @TA("array") Dummy[] dummy;
+ public @TA("wildcard") GetAnnotatedOwnerType<?> wildcard;
+ public @TA("typevariable") Dummy tv;
+ public @TA("bad") GetAnnotatedOwnerType<@TA("good") GetAnnotatedOwnerType<String> . @TB("tb") Nested<Integer> > typeArgument;
+ public GetAnnotatedOwnerType< GetAnnotatedOwnerType<String> .
+ B .
+ C<Class<?>, ? extends @TA("complicated") Exception> .
+ D<Number> > [] complicated;
+
+ public static void main(String[] args) throws Exception {
+ testGeneric();
+ testRaw();
+ testNonGeneric();
+ testInnerGeneric();
+ testInnerRaw();
+
+ testLocalClass();
+ testAnonymousClass();
+
+ testArray();
+ testWildcard();
+ testTypeParameter();
+
+ testTypeArgument();
+ testComplicated();
+ }
+
+ public static void testGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("genericField");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testRaw() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("rawField");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "raw");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testNonGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("nonGeneric");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "non-generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testInnerGeneric() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("innerGeneric");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "generic");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((ParameterizedType) f.getGenericType()).getOwnerType());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testInnerRaw() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("innerRaw");
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = f.getAnnotatedType();
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "raw");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated, on the correct type
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getType(), ((Class<?>)f.getGenericType()).getEnclosingClass());
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "non-generic");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testLocalClass() throws Exception {
+ class ALocalClass {}
+ class OneMore {
+ public @TA("null") ALocalClass c;
+ }
+ testNegative(OneMore.class.getField("c").getAnnotatedType(), "Local class should return null");
+ }
+
+ public static void testAnonymousClass() throws Exception {
+ testNegative(GetAnnotatedOwnerType.class.getField("anonymous").getAnnotatedType(),
+ "Anonymous class should return null");
+ }
+
+ public static void testArray() throws Exception {
+ AnnotatedType t = GetAnnotatedOwnerType.class.getField("dummy").getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedArrayType),
+ "Was expecting an AnnotatedArrayType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testWildcard() throws Exception {
+ AnnotatedType tt = GetAnnotatedOwnerType.class.getField("wildcard").getAnnotatedType();
+ AnnotatedType t = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertTrue((t instanceof AnnotatedWildcardType),
+ "Was expecting an AnnotatedWildcardType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testTypeParameter() throws Exception {
+ AnnotatedType t = GetAnnotatedOwnerType.class.getField("tv").getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedTypeVariable),
+ "Was expecting an AnnotatedTypeVariable " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ }
+
+ public static void testTypeArgument() throws Exception {
+ AnnotatedType tt = GetAnnotatedOwnerType.class.getField("typeArgument").getAnnotatedType();
+ Asserts.assertEquals(tt.getAnnotation(TA.class).value(), "bad");
+ Asserts.assertTrue(tt.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + tt.getAnnotations().length);
+
+ // make sure inner is correctly annotated
+ AnnotatedType inner = ((AnnotatedParameterizedType)tt).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertEquals(inner.getAnnotation(TB.class).value(), "tb");
+ Asserts.assertTrue(inner.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + inner.getAnnotations().length);
+
+ // make sure owner is correctly annotated
+ AnnotatedType outer = inner.getAnnotatedOwnerType();
+ Asserts.assertEquals(outer.getAnnotation(TA.class).value(), "good");
+ Asserts.assertTrue(outer.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + outer.getAnnotations().length);
+ }
+
+ public static void testComplicated() throws Exception {
+ Field f = GetAnnotatedOwnerType.class.getField("complicated");
+
+ // Outermost level
+ AnnotatedType t = f.getAnnotatedType();
+ Asserts.assertTrue((t instanceof AnnotatedArrayType),
+ "Was expecting an AnnotatedArrayType " + t);
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // Component type
+ t = ((AnnotatedArrayType)t).getAnnotatedGenericComponentType();
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // Type arg GetAnnotatedOwnerType<String>...D<Number>
+ t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[0];
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // C<Class<?>, ? extends ...>
+ t = t.getAnnotatedOwnerType();
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // ? extends
+ t = ((AnnotatedParameterizedType)t).getAnnotatedActualTypeArguments()[1];
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertTrue(t.getAnnotations().length == 0, "expecting zero annotation, got: "
+ + t.getAnnotations().length);
+
+ // @TA("complicated") Exception
+ t = ((AnnotatedWildcardType)t).getAnnotatedUpperBounds()[0];
+ testNegative(t, "" + t + " should not have an annotated owner type");
+ Asserts.assertEquals(t.getAnnotation(TA.class).value(), "complicated");
+ Asserts.assertTrue(t.getAnnotations().length == 1, "expecting one (1) annotation, got: "
+ + t.getAnnotations().length);
+ }
+
+ private static void testNegative(AnnotatedType t, String msg) {
+ Asserts.assertNull(t.getAnnotatedOwnerType(), msg);
+ }
+
+ public class Nested<AlsoDummy> {}
+ public class B {
+ public class C<R, S> {
+ public class D<T> {
+ }
+ }
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface TA {
+ String value();
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @Retention(RetentionPolicy.RUNTIME)
+ public @interface TB {
+ String value();
+ }
+}
+
+class GetAnnotatedOwnerTypeAuxilliary {
+ class Inner {}
+
+ class InnerGeneric<Dummy> {}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ref/CleanerTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,705 @@
+/*
+ * 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.ref.Cleaner;
+import java.lang.ref.Reference;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.lang.ref.WeakReference;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import jdk.internal.misc.CleanerImpl.PhantomCleanable;
+import jdk.internal.misc.CleanerImpl.WeakCleanable;
+import jdk.internal.misc.CleanerImpl.SoftCleanable;
+
+import sun.hotspot.WhiteBox;
+
+import org.testng.Assert;
+import org.testng.TestNG;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @library /lib/testlibrary /test/lib
+ * @build sun.hotspot.WhiteBox
+ * @modules java.base/jdk.internal.misc
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run testng/othervm
+ * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -verbose:gc -Xmx4m CleanerTest
+ */
+
+@Test
+public class CleanerTest {
+ // A common CleaningService used by the test for notifications
+ static final Cleaner COMMON = Cleaner.create();
+
+ // Access to WhiteBox utilities
+ static final WhiteBox whitebox = WhiteBox.getWhiteBox();
+
+ /**
+ * Test that sequences of the various actions on a Reference
+ * and on the Cleanable instance have the desired result.
+ * The test cases are generated for each of phantom, weak and soft
+ * references.
+ * The sequence of actions includes all permutations to an initial
+ * list of actions including clearing the ref and resulting garbage
+ * collection actions on the reference and explicitly performing
+ * the cleaning action.
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ void testCleanableActions() {
+ Cleaner cleaner = Cleaner.create();
+
+ // Individually
+ generateCases(cleaner, c -> c.clearRef());
+ generateCases(cleaner, c -> c.doClean());
+
+ // Pairs
+ generateCases(cleaner, c -> c.doClean(), c -> c.clearRef());
+
+ CleanableCase s = setupPhantom(COMMON, cleaner);
+ cleaner = null;
+ Assert.assertTrue(checkCleaned(s.getSemaphore()),
+ "Cleaner cleanup should have occurred");
+ }
+
+ /**
+ * Test the jdk.internal.misc APIs with sequences of the various actions
+ * on a Reference and on the Cleanable instance have the desired result.
+ * The test cases are generated for each of phantom, weak and soft
+ * references.
+ * The sequence of actions includes all permutations to an initial
+ * list of actions including clearing the ref and resulting garbage
+ * collection actions on the reference, explicitly performing
+ * the cleanup and explicitly clearing the cleaning action.
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ void testRefSubtypes() {
+ Cleaner cleaner = Cleaner.create();
+
+ // Individually
+ generateCasesInternal(cleaner, c -> c.clearRef());
+ generateCasesInternal(cleaner, c -> c.doClean());
+ generateCasesInternal(cleaner, c -> c.doClear());
+
+ // Pairs
+ generateCasesInternal(cleaner,
+ c -> c.doClear(), c -> c.doClean());
+
+ // Triplets
+ generateCasesInternal(cleaner,
+ c -> c.doClear(), c -> c.doClean(), c -> c.clearRef());
+
+ generateExceptionCasesInternal(cleaner);
+
+ CleanableCase s = setupPhantom(COMMON, cleaner);
+ cleaner = null;
+ Assert.assertTrue(checkCleaned(s.getSemaphore()),
+ "Cleaner cleanup should have occurred");
+ }
+
+ /**
+ * Generate tests using the runnables for each of phantom, weak,
+ * and soft references.
+ * @param cleaner the cleaner
+ * @param runnables the sequence of actions on the test case
+ */
+ @SuppressWarnings("unchecked")
+ void generateCases(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
+ generateCases(() -> setupPhantom(cleaner, null), runnables.length, runnables);
+ }
+
+ @SuppressWarnings("unchecked")
+ void generateCasesInternal(Cleaner cleaner, Consumer<CleanableCase>... runnables) {
+ generateCases(() -> setupPhantomSubclass(cleaner, null),
+ runnables.length, runnables);
+ generateCases(() -> setupWeakSubclass(cleaner, null),
+ runnables.length, runnables);
+ generateCases(() -> setupSoftSubclass(cleaner, null),
+ runnables.length, runnables);
+ }
+
+ @SuppressWarnings("unchecked")
+ void generateExceptionCasesInternal(Cleaner cleaner) {
+ generateCases(() -> setupPhantomSubclassException(cleaner, null),
+ 1, c -> c.clearRef());
+ generateCases(() -> setupWeakSubclassException(cleaner, null),
+ 1, c -> c.clearRef());
+ generateCases(() -> setupSoftSubclassException(cleaner, null),
+ 1, c -> c.clearRef());
+ }
+
+ /**
+ * Generate all permutations of the sequence of runnables
+ * and test each one.
+ * The permutations are generated using Heap, B.R. (1963) Permutations by Interchanges.
+ * @param generator the supplier of a CleanableCase
+ * @param n the first index to interchange
+ * @param runnables the sequence of actions
+ */
+ @SuppressWarnings("unchecked")
+ void generateCases(Supplier<CleanableCase> generator, int n,
+ Consumer<CleanableCase> ... runnables) {
+ if (n == 1) {
+ CleanableCase test = generator.get();
+ try {
+ verifyGetRef(test);
+
+ // Apply the sequence of actions on the Ref
+ for (Consumer<CleanableCase> c : runnables) {
+ c.accept(test);
+ }
+ verify(test);
+ } catch (Exception e) {
+ Assert.fail(test.toString(), e);
+ }
+ } else {
+ for (int i = 0; i < n - 1; i += 1) {
+ generateCases(generator, n - 1, runnables);
+ Consumer<CleanableCase> t = runnables[n - 1];
+ int ndx = ((n & 1) == 0) ? i : 0;
+ runnables[n - 1] = runnables[ndx];
+ runnables[ndx] = t;
+ }
+ generateCases(generator, n - 1, runnables);
+ }
+ }
+
+ /**
+ * Verify the test case.
+ * Any actions directly on the Reference or Cleanable have been executed.
+ * The CleanableCase under test is given a chance to do the cleanup
+ * by forcing a GC.
+ * The result is compared with the expected result computed
+ * from the sequence of operations on the Cleanable.
+ * The Cleanable itself should have been cleanedup.
+ *
+ * @param test A CleanableCase containing the references
+ */
+ void verify(CleanableCase test) {
+ System.out.println(test);
+ int r = test.expectedResult();
+
+ CleanableCase cc = setupPhantom(COMMON, test.getCleanable());
+ test.clearCleanable(); // release this hard reference
+
+ boolean result = checkCleaned(test.getSemaphore());
+ if (result) {
+ Assert.assertEquals(r, CleanableCase.EV_CLEAN,
+ "cleaned; but not expected");
+ } else {
+ Assert.assertNotEquals(r, CleanableCase.EV_CLEAN,
+ "not cleaned; expected cleaning");
+ }
+ Assert.assertTrue(checkCleaned(cc.getSemaphore()),
+ "The reference to the Cleanable should have been freed");
+ }
+
+ /**
+ * Verify that the reference.get works (or not) as expected.
+ * It handles the cases where UnsupportedOperationException is expected.
+ *
+ * @param test the CleanableCase
+ */
+ void verifyGetRef(CleanableCase test) {
+ Reference<?> r = (Reference) test.getCleanable();
+ try {
+ Object o = r.get();
+ Reference<?> expectedRef = test.getRef();
+ Assert.assertEquals(expectedRef.get(), o,
+ "Object reference incorrect");
+ if (r.getClass().getName().endsWith("CleanableRef")) {
+ Assert.fail("should not be able to get referent");
+ }
+ } catch (UnsupportedOperationException uoe) {
+ if (r.getClass().getName().endsWith("CleanableRef")) {
+ // Expected exception
+ } else {
+ Assert.fail("Unexpected exception from subclassed cleanable: " +
+ uoe.getMessage() + ", class: " + r.getClass());
+ }
+ }
+ }
+
+ /**
+ * Test that releasing the reference to the Cleaner service allows it to be
+ * be freed.
+ */
+ @Test
+ void testCleanerTermination() {
+ ReferenceQueue<Object> queue = new ReferenceQueue<>();
+ Cleaner service = Cleaner.create();
+
+ PhantomReference<Object> ref = new PhantomReference<>(service, queue);
+ System.gc();
+ // Clear the Reference to the cleaning service and force a gc.
+ service = null;
+ System.gc();
+ try {
+ Reference<?> r = queue.remove(1000L);
+ Assert.assertNotNull(r, "queue.remove timeout,");
+ Assert.assertEquals(r, ref, "Wrong Reference dequeued");
+ } catch (InterruptedException ie) {
+ System.out.printf("queue.remove Interrupted%n");
+ }
+ }
+
+ /**
+ * Check a semaphore having been released by cleanup handler.
+ * Force a number of GC cycles to give the GC a chance to process
+ * the Reference and for the cleanup action to be run.
+ *
+ * @param semaphore a Semaphore
+ * @return true if the semaphores has 1 permit, false otherwise.
+ */
+ static boolean checkCleaned(Semaphore semaphore) {
+ int cycle = 0;
+ for (; cycle < 3; cycle++) {
+ try {
+ if (semaphore.tryAcquire(10L, TimeUnit.MILLISECONDS)) {
+ System.out.printf(" Cleanable cleaned in cycle: %d%n", cycle);
+ return true;
+ }
+ } catch (InterruptedException ie) {
+ // retry in outer loop
+ }
+ // Force GC
+ whitebox.fullGC();
+ }
+ // Object has not been cleaned
+ System.out.printf(" Cleanable not cleaned%n");
+ return false; // Failing result
+ }
+
+ /**
+ * Create a CleanableCase for a PhantomReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupPhantom(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+ Cleaner.Cleanable c1 = cleaner.register(obj, () -> s1.release());
+
+ return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
+ }
+
+ /**
+ * Create a CleanableCase for a PhantomReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupPhantomSubclass(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ }
+ };
+
+ return new CleanableCase(new PhantomReference<>(obj, null), c1, s1);
+ }
+ /**
+ * Create a CleanableCase for a WeakReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupWeakSubclass(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ }
+ };
+
+ return new CleanableCase(new WeakReference<>(obj, null), c1, s1);
+ }
+
+ /**
+ * Create a CleanableCase for a SoftReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupSoftSubclass(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ }
+ };
+
+ return new CleanableCase(new SoftReference<>(obj, null), c1, s1);
+ }
+
+ /**
+ * Create a CleanableCase for a PhantomReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupPhantomSubclassException(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new PhantomCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ throw new RuntimeException("Exception thrown to cleaner thread");
+ }
+ };
+
+ return new CleanableCase(new PhantomReference<>(obj, null), c1, s1, true);
+ }
+
+ /**
+ * Create a CleanableCase for a WeakReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupWeakSubclassException(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new WeakCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ throw new RuntimeException("Exception thrown to cleaner thread");
+ }
+ };
+
+ return new CleanableCase(new WeakReference<>(obj, null), c1, s1, true);
+ }
+
+ /**
+ * Create a CleanableCase for a SoftReference.
+ * @param cleaner the cleaner to use
+ * @param obj an object or null to create a new Object
+ * @return a new CleanableCase preset with the object, cleanup, and semaphore
+ */
+ static CleanableCase setupSoftSubclassException(Cleaner cleaner, Object obj) {
+ if (obj == null) {
+ obj = new Object();
+ }
+ Semaphore s1 = new Semaphore(0);
+
+ Cleaner.Cleanable c1 = new SoftCleanable<Object>(obj, cleaner) {
+ protected void performCleanup() {
+ s1.release();
+ throw new RuntimeException("Exception thrown to cleaner thread");
+ }
+ };
+
+ return new CleanableCase(new SoftReference<>(obj, null), c1, s1, true);
+ }
+
+ /**
+ * CleanableCase encapsulates the objects used for a test.
+ * The reference to the object is not held directly,
+ * but in a Reference object that can be cleared.
+ * The semaphore is used to count whether the cleanup occurred.
+ * It can be awaited on to determine that the cleanup has occurred.
+ * It can be checked for non-zero to determine if it was
+ * invoked or if it was invoked twice (a bug).
+ */
+ static class CleanableCase {
+
+ private volatile Reference<?> ref;
+ private volatile Cleaner.Cleanable cleanup;
+ private final Semaphore semaphore;
+ private final boolean throwsEx;
+ private final int[] events; // Sequence of calls to clean, clear, etc.
+ private volatile int eventNdx;
+
+ public static int EV_UNKNOWN = 0;
+ public static int EV_CLEAR = 1;
+ public static int EV_CLEAN = 2;
+ public static int EV_UNREF = 3;
+ public static int EV_CLEAR_CLEANUP = 4;
+
+
+ CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
+ Semaphore semaphore) {
+ this.ref = ref;
+ this.cleanup = cleanup;
+ this.semaphore = semaphore;
+ this.throwsEx = false;
+ this.events = new int[4];
+ this.eventNdx = 0;
+ }
+ CleanableCase(Reference<Object> ref, Cleaner.Cleanable cleanup,
+ Semaphore semaphore,
+ boolean throwsEx) {
+ this.ref = ref;
+ this.cleanup = cleanup;
+ this.semaphore = semaphore;
+ this.throwsEx = throwsEx;
+ this.events = new int[4];
+ this.eventNdx = 0;
+ }
+
+ public Reference<?> getRef() {
+ return ref;
+ }
+
+ public void clearRef() {
+ addEvent(EV_UNREF);
+ ref.clear();
+ }
+
+ public Cleaner.Cleanable getCleanable() {
+ return cleanup;
+ }
+
+ public void doClean() {
+ try {
+ addEvent(EV_CLEAN);
+ cleanup.clean();
+ } catch (RuntimeException ex) {
+ if (!throwsEx) {
+ // unless it is known this case throws an exception, rethrow
+ throw ex;
+ }
+ }
+ }
+
+ public void doClear() {
+ addEvent(EV_CLEAR);
+ ((Reference)cleanup).clear();
+ }
+
+ public void clearCleanable() {
+ addEvent(EV_CLEAR_CLEANUP);
+ cleanup = null;
+ }
+
+ public Semaphore getSemaphore() {
+ return semaphore;
+ }
+
+ public boolean isCleaned() {
+ return semaphore.availablePermits() != 0;
+ }
+
+ private synchronized void addEvent(int e) {
+ events[eventNdx++] = e;
+ }
+
+ /**
+ * Computed the expected result from the sequence of events.
+ * If EV_CLEAR appears before anything else, it is cleared.
+ * If EV_CLEAN appears before EV_UNREF, then it is cleaned.
+ * Anything else is Unknown.
+ * @return EV_CLEAR if the cleanup should occur;
+ * EV_CLEAN if the cleanup should occur;
+ * EV_UNKNOWN if it is unknown.
+ */
+ public synchronized int expectedResult() {
+ // Test if EV_CLEAR appears before anything else
+ int clearNdx = indexOfEvent(EV_CLEAR);
+ int cleanNdx = indexOfEvent(EV_CLEAN);
+ int unrefNdx = indexOfEvent(EV_UNREF);
+ if (clearNdx < cleanNdx) {
+ return EV_CLEAR;
+ }
+ if (cleanNdx < clearNdx || cleanNdx < unrefNdx) {
+ return EV_CLEAN;
+ }
+ if (unrefNdx < eventNdx) {
+ return EV_CLEAN;
+ }
+
+ return EV_UNKNOWN;
+ }
+
+ private synchronized int indexOfEvent(int e) {
+ for (int i = 0; i < eventNdx; i++) {
+ if (events[i] == e) {
+ return i;
+ }
+ }
+ return eventNdx;
+ }
+
+ private static final String[] names =
+ {"UNKNOWN", "EV_CLEAR", "EV_CLEAN", "EV_UNREF", "EV_CLEAR_CLEANUP"};
+
+ public String eventName(int event) {
+ return names[event];
+ }
+
+ public synchronized String eventsString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append('[');
+ for (int i = 0; i < eventNdx; i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(eventName(events[i]));
+ }
+ sb.append(']');
+ sb.append(", throwEx: ");
+ sb.append(throwsEx);
+ return sb.toString();
+ }
+
+ public String toString() {
+ return String.format("Case: %s, expect: %s, events: %s",
+ getRef().getClass().getName(),
+ eventName(expectedResult()), eventsString());
+ }
+ }
+
+
+ /**
+ * Example using a Cleaner to remove WeakKey references from a Map.
+ */
+ @Test
+ void testWeakKey() {
+ ConcurrentHashMap<WeakKey<String>, String> map = new ConcurrentHashMap<>();
+ Cleaner cleaner = Cleaner.create();
+ String key = new String("foo"); // ensure it is not interned
+ String data = "bar";
+
+ map.put(new WeakKey<>(key, cleaner, map), data);
+
+ WeakKey<String> k2 = new WeakKey<>(key, cleaner, map);
+
+ Assert.assertEquals(map.get(k2), data, "value should be found in the map");
+ key = null;
+ System.gc();
+ Assert.assertNotEquals(map.get(k2), data, "value should not be found in the map");
+
+ final int CYCLE_MAX = 30;
+ for (int i = 1; map.size() > 0 && i < CYCLE_MAX; i++) {
+ map.forEach( (k, v) -> System.out.printf(" k: %s, v: %s%n", k, v));
+ try {
+ Thread.sleep(10L);
+ } catch (InterruptedException ie) {}
+ }
+ Assert.assertEquals(map.size(), 0, "Expected map to be empty;");
+ cleaner = null;
+ }
+
+ /**
+ * Test sample class for WeakKeys in Map.
+ * @param <K> A WeakKey of type K
+ */
+ class WeakKey<K> extends WeakReference<K> {
+ private final int hash;
+ private final ConcurrentHashMap<WeakKey<K>, ?> map;
+ Cleaner.Cleanable cleanable;
+
+ public WeakKey(K key, Cleaner c, ConcurrentHashMap<WeakKey<K>, ?> map) {
+ super(key);
+ this.hash = key.hashCode();
+ this.map = map;
+ cleanable = new WeakCleanable<Object>(key, c) {
+ protected void performCleanup() {
+ map.remove(WeakKey.this);
+ }
+ };
+ }
+ public int hashCode() { return hash; }
+
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof WeakKey)) return false;
+ K key = get();
+ if (key == null) return obj == this;
+ return key == ((WeakKey<?>)obj).get();
+ }
+
+ public String toString() {
+ return "WeakKey:" + Objects.toString(get() + ", cleanableRef: " +
+ ((Reference)cleanable).get());
+ }
+ }
+
+ /**
+ * Verify that casting a Cleanup to a Reference is not allowed to
+ * get the referent or clear the reference.
+ */
+ @Test
+ @SuppressWarnings("rawtypes")
+ void testReferentNotAvailable() {
+ Cleaner cleaner = Cleaner.create();
+ Semaphore s1 = new Semaphore(0);
+
+ Object obj = new String("a new string");
+ Cleaner.Cleanable c = cleaner.register(obj, () -> s1.release());
+ Reference r = (Reference) c;
+ try {
+ Object o = r.get();
+ System.out.printf("r: %s%n", Objects.toString(o));
+ Assert.fail("should not be able to get the referent from Cleanable");
+ } catch (UnsupportedOperationException uoe) {
+ // expected
+ }
+
+ try {
+ r.clear();
+ Assert.fail("should not be able to clear the referent from Cleanable");
+ } catch (UnsupportedOperationException uoe) {
+ // expected
+ }
+
+ obj = null;
+ Assert.assertTrue(checkCleaned(s1), "reference should be cleaned;");
+ cleaner = null;
+ }
+
+}
--- a/jdk/test/java/lang/reflect/Proxy/CharType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/lang/reflect/Proxy/CharType.java Wed Jan 06 14:54:24 2016 +0000
@@ -24,7 +24,7 @@
/*
* @test
* @bug 4346224
- * @summary Test against a typo in sun.misc.ProxyGenerator:
+ * @summary Test against a typo in ProxyGenerator:
* "java/lang/Character" should be used instead of
* "java/lang/Char".
*/
--- a/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/net/NetworkInterface/NetworkInterfaceStreamTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,13 +22,12 @@
*/
/* @test
- * @bug 8081678
+ * @bug 8081678 8131155
* @summary Tests for stream returning methods
* @library ../../util/stream/bootlib/java.base
* @build java.util.stream.OpTestCase
* @run testng/othervm NetworkInterfaceStreamTest
* @run testng/othervm -Djava.net.preferIPv4Stack=true NetworkInterfaceStreamTest
- * @key intermittent
*/
import org.testng.annotations.Test;
@@ -46,6 +45,8 @@
public class NetworkInterfaceStreamTest extends OpTestCase {
+ private final static boolean IS_WINDOWS = System.getProperty("os.name").startsWith("Windows");
+
@Test
public void testNetworkInterfaces() throws SocketException {
Supplier<Stream<NetworkInterface>> ss = () -> {
@@ -74,7 +75,9 @@
}
private void getAllSubNetworkInterfaces(NetworkInterface ni, Collection<NetworkInterface> result) {
- result.add(ni);
+ if (isIncluded(ni)) {
+ result.add(ni);
+ }
for (NetworkInterface sni : Collections.list(ni.getSubInterfaces())) {
getAllSubNetworkInterfaces(sni, result);
@@ -82,13 +85,15 @@
}
private Stream<NetworkInterface> allNetworkInterfaces() throws SocketException {
- return NetworkInterface.networkInterfaces().flatMap(this::allSubNetworkInterfaces);
+ return NetworkInterface.networkInterfaces()
+ .filter(ni -> isIncluded(ni))
+ .flatMap(this::allSubNetworkInterfaces);
}
private Stream<NetworkInterface> allSubNetworkInterfaces(NetworkInterface ni) {
return Stream.concat(
Stream.of(ni),
- ni.subInterfaces().flatMap(this::allSubNetworkInterfaces));
+ ni.subInterfaces().filter(sni -> isIncluded(sni)).flatMap(this::allSubNetworkInterfaces));
}
@Test
@@ -114,7 +119,9 @@
public void testInetAddresses() throws SocketException {
Supplier<Stream<InetAddress>> ss = () -> {
try {
- return NetworkInterface.networkInterfaces().flatMap(NetworkInterface::inetAddresses);
+ return NetworkInterface.networkInterfaces()
+ .filter(ni -> isIncluded(ni))
+ .flatMap(NetworkInterface::inetAddresses);
}
catch (SocketException e) {
throw new RuntimeException(e);
@@ -124,7 +131,9 @@
Collection<NetworkInterface> nis = Collections.list(NetworkInterface.getNetworkInterfaces());
Collection<InetAddress> expected = new ArrayList<>();
for (NetworkInterface ni : nis) {
- expected.addAll(Collections.list(ni.getInetAddresses()));
+ if (isIncluded(ni)) {
+ expected.addAll(Collections.list(ni.getInetAddresses()));
+ }
}
withData(TestData.Factory.ofSupplier("All inet addresses", ss))
.stream(s -> s)
@@ -132,5 +141,21 @@
.exercise();
}
+ /**
+ * Check if the input network interface should be included in the test. It is necessary to exclude
+ * "Teredo Tunneling Pseudo-Interface" whose configuration can be variable during a test run.
+ *
+ * @param ni a network interace
+ * @return false if it is a "Teredo Tunneling Pseudo-Interface", otherwise true.
+ */
+ private boolean isIncluded(NetworkInterface ni) {
+ if (!IS_WINDOWS) {
+ return true;
+ }
+
+ String dName = ni.getDisplayName();
+ return dName == null || !dName.contains("Teredo");
+ }
}
+
--- a/jdk/test/java/net/URL/TestPort.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/net/URL/TestPort.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,28 +23,33 @@
/*
* @test
- * @bug 4101492 4444213
+ * @bug 4101492 4444213 4906983
* @summary The java.net.URL constructor allows port < 0 and port > 65535
*/
import java.net.*;
public class TestPort {
- public static void main(String[] args) {
- URL url = null;
+ public static void main(String[] args) throws MalformedURLException {
+ // URLs are able to have port bigger than TCP-Port 65535 and
+ // to have no port (-1) at all.:
+ URL url = new URL("http","server",Integer.MAX_VALUE,"/path");
+ url = new URL("http://server:"+Integer.MAX_VALUE+"/path");
+ url = new URL("http://server/path");
+ url = new URL("http","server",-1,"/path");
+
try {
url = new URL("ftp", "java.sun.com", -20, "/pub/");
+ throw new RuntimeException("MalformedURLException not thrown!");
} catch (MalformedURLException e) {
- url = null;
+ // Everything fine. MalformedURLException expected
}
- if (url != null)
- throw new RuntimeException("MalformedURLException not thrown!");
+
try {
url = new URL("ftp://java.sun.com:-20/pub/");
+ throw new RuntimeException("MalformedURLException not thrown!");
} catch (MalformedURLException e) {
- url = null;
+ // Everything fine. MalformedURLException expected
}
- if (url != null)
- throw new RuntimeException("MalformedURLException not thrown!");
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/WatchService/UpdateInterference.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8145981
+ * @summary LinuxWatchService sometimes reports inotify events against wrong directory
+ * @run main UpdateInterference
+ */
+import java.io.IOException;
+import java.nio.file.*;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import static java.nio.file.StandardWatchEventKinds.*;
+
+public class UpdateInterference {
+ public static void main(String[] args) throws IOException, InterruptedException {
+ final Path root = Files.createTempDirectory("test");
+ final Path foo = root.resolve("foo");
+ final Path bar = root.resolve("bar");
+ final Path baz = root.resolve("baz");
+
+ Files.createDirectory(foo);
+ Files.createDirectory(bar);
+ Files.createDirectory(baz);
+
+ final WatchService watcher = root.getFileSystem().newWatchService();
+ final WatchKey fooKey = foo.register(watcher, ENTRY_CREATE);
+ final WatchKey barKey = bar.register(watcher, ENTRY_CREATE);
+
+ new Thread() {
+ { setDaemon(true); }
+
+ @Override
+ public void run() {
+ while (true) {
+ try {
+ final Path temp = Files.createTempFile(foo, "temp", ".tmp");
+ Files.delete(temp);
+ Thread.sleep(10);
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }.start();
+
+ new Thread() {
+ { setDaemon(true); }
+
+ @Override
+ public void run() {
+ WatchKey bazKeys[] = new WatchKey[32];
+ while (true) {
+ try {
+ for( int i = 0; i < bazKeys.length; i++) {
+ bazKeys[i] = baz.register(watcher, ENTRY_CREATE);
+ }
+ for( int i = 0; i < bazKeys.length; i++) {
+ bazKeys[i].cancel();
+ }
+ Thread.sleep(1);
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }.start();
+
+ long time = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - time) < 15000) {
+ final WatchKey key = watcher.poll(60, TimeUnit.SECONDS);
+ if (key == null) continue;
+
+ if (key != fooKey) {
+ List<WatchEvent<?>> pollEvents = key.pollEvents();
+ for (WatchEvent<?> watchEvent : pollEvents) {
+ System.out.println(watchEvent.count() + " " +
+ watchEvent.kind() + " " +
+ watchEvent.context());
+ }
+ throw new RuntimeException("Event received for unexpected key");
+ }
+ key.reset();
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/text/Format/DateFormat/Bug8139572.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8139572
+ * @summary SimpleDateFormat parse month stand-alone format bug
+ * @compile -encoding utf-8 Bug8139572.java
+ * @run main Bug8139572
+ */
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+
+public class Bug8139572 {
+
+ private static final Locale RUSSIAN = new Locale("ru");
+ private static final Date SEPT12 = new GregorianCalendar(2015, Calendar.SEPTEMBER, 12).getTime();
+
+ private static final String[] PATTERNS = {
+ "L",
+ "dd L",
+ "dd L yy",
+ "dd L yyyy",
+ "LL",
+ "dd LL",
+ "dd LL yy",
+ "dd LL yyyy",
+ "LLL",
+ "dd LLL",
+ "dd LLL yy",
+ "dd LLL yyyy",
+ "LLLL",
+ "dd LLLL",
+ "dd LLLL yy",
+ "dd LLLL yyyy"
+ };
+
+ private static final String[] APPLIED = {
+ "9",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "09",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "сентября",
+ "12 сентября",
+ "12 сентября 15",
+ "12 сентября 2015",
+ "сентября",
+ "12 сентября",
+ "12 сентября 15",
+ "12 сентября 2015"
+ };
+
+ private static final String[] EXPECTED = {
+ "9",
+ "12 9",
+ "12 9 15",
+ "12 9 2015",
+ "09",
+ "12 09",
+ "12 09 15",
+ "12 09 2015",
+ "сент.",
+ "12 сент.",
+ "12 сент. 15",
+ "12 сент. 2015",
+ "сентябрь",
+ "12 сентябрь",
+ "12 сентябрь 15",
+ "12 сентябрь 2015"
+ };
+
+ public static void main(String[] args) throws ParseException {
+
+ for (int i = 0; i < PATTERNS.length; i++) {
+ SimpleDateFormat fmt = new SimpleDateFormat(PATTERNS[i], RUSSIAN);
+ Date standAloneDate = fmt.parse(APPLIED[i]);
+ String str = fmt.format(standAloneDate);
+ if (!EXPECTED[i].equals(str)) {
+ throw new RuntimeException("bad result: got '" + str + "', expected '" + EXPECTED[i] + "'");
+ }
+ }
+
+ SimpleDateFormat fmt = new SimpleDateFormat("", RUSSIAN);
+ for (int j = 0; j < PATTERNS.length; j++) {
+ fmt.applyPattern(PATTERNS[j]);
+ String str = fmt.format(SEPT12);
+ if (!EXPECTED[j].equals(str)) {
+ throw new RuntimeException("bad result: got '" + str + "', expected '" + EXPECTED[j] + "'");
+ }
+ }
+ }
+}
--- a/jdk/test/java/time/tck/java/time/TCKDuration.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/time/tck/java/time/TCKDuration.java Wed Jan 06 14:54:24 2016 +0000
@@ -2393,6 +2393,65 @@
}
//-----------------------------------------------------------------------
+ // dividedbyDur()
+ //-----------------------------------------------------------------------
+
+ @DataProvider(name="dividedByDur_provider")
+ Object[][] provider_dividedByDur() {
+ return new Object[][] {
+ {Duration.ofSeconds(0, 0), Duration.ofSeconds(1, 0), 0},
+ {Duration.ofSeconds(1, 0), Duration.ofSeconds(1, 0), 1},
+ {Duration.ofSeconds(6, 0), Duration.ofSeconds(3, 0), 2},
+ {Duration.ofSeconds(3, 0), Duration.ofSeconds(6, 0), 0},
+ {Duration.ofSeconds(7, 0), Duration.ofSeconds(3, 0), 2},
+
+ {Duration.ofSeconds(0, 333_333_333), Duration.ofSeconds(0, 333_333_333), 1},
+ {Duration.ofSeconds(0, 666_666_666), Duration.ofSeconds(0, 333_333_333), 2},
+ {Duration.ofSeconds(0, 333_333_333), Duration.ofSeconds(0, 666_666_666), 0},
+ {Duration.ofSeconds(0, 777_777_777), Duration.ofSeconds(0, 333_333_333), 2},
+
+ {Duration.ofSeconds(-7, 0), Duration.ofSeconds(3, 0), -2},
+ {Duration.ofSeconds(0, 7), Duration.ofSeconds(0, -3), -2},
+ {Duration.ofSeconds(0, -777_777_777), Duration.ofSeconds(0, 333_333_333), -2},
+
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), 29},
+ {Duration.ofSeconds(-432000L, 777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(14400L, 333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(14400L, -333_333_333L), -30},
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(-14400L, 333_333_333L), -30},
+ {Duration.ofSeconds(432000L, -777_777_777L), Duration.ofSeconds(-14400L, -333_333_333L), -29},
+ {Duration.ofSeconds(-432000L, -777_777_777L), Duration.ofSeconds(-14400L, -333_333_333L), 29},
+
+ {Duration.ofSeconds(Long.MAX_VALUE, 0), Duration.ofSeconds(1, 0), Long.MAX_VALUE},
+ {Duration.ofSeconds(Long.MAX_VALUE, 0), Duration.ofSeconds(Long.MAX_VALUE, 0), 1},
+ };
+ }
+
+ @Test(dataProvider="dividedByDur_provider")
+ public void test_dividedByDur(Duration dividend, Duration divisor, long expected) {
+ assertEquals(dividend.dividedBy(divisor), expected);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void test_dividedByDur_zero() {
+ Duration t = Duration.ofSeconds(1, 0);
+ t.dividedBy(Duration.ZERO);
+ }
+
+ @Test(expectedExceptions=NullPointerException.class)
+ public void test_dividedByDur_null() {
+ Duration t = Duration.ofSeconds(1, 0);
+ t.dividedBy(null);
+ }
+
+ @Test(expectedExceptions=ArithmeticException.class)
+ public void test_dividedByDur_overflow() {
+ Duration dur1 = Duration.ofSeconds(Long.MAX_VALUE, 0);
+ Duration dur2 = Duration.ofNanos(1);
+ dur1.dividedBy(dur2);
+ }
+
+ //-----------------------------------------------------------------------
// negated()
//-----------------------------------------------------------------------
@Test
--- a/jdk/test/java/time/tck/java/time/TCKLocalDate.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/time/tck/java/time/TCKLocalDate.java Wed Jan 06 14:54:24 2016 +0000
@@ -2157,6 +2157,31 @@
}
//-----------------------------------------------------------------------
+ // toEpochSecond
+ //-----------------------------------------------------------------------
+ @DataProvider(name="epochSecond")
+ Object[][] provider_toEpochSecond() {
+ return new Object[][] {
+ {LocalDate.of(1858, 11, 17).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_PONE), -3506720400L},
+ {LocalDate.of(1, 1, 1).toEpochSecond(LocalTime.NOON, OFFSET_PONE), -62135557200L},
+ {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.of(5, 30), OFFSET_PTWO), 812172600L},
+ {LocalDate.of(1970, 1, 1).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_MTWO), 7200L},
+ {LocalDate.of(-1, 12, 31).toEpochSecond(LocalTime.NOON, OFFSET_PONE), -62167266000L},
+ {LocalDate.of(1, 1, 1).toEpochSecond(LocalTime.MIDNIGHT, OFFSET_PONE),
+ Instant.ofEpochSecond(-62135600400L).getEpochSecond()},
+ {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.NOON, OFFSET_PTWO),
+ Instant.ofEpochSecond(812196000L).getEpochSecond()},
+ {LocalDate.of(1995, 9, 27).toEpochSecond(LocalTime.of(5, 30), OFFSET_MTWO),
+ LocalDateTime.of(1995, 9, 27, 5, 30).toEpochSecond(OFFSET_MTWO)},
+ };
+ }
+
+ @Test(dataProvider="epochSecond")
+ public void test_toEpochSecond(long actual, long expected) {
+ assertEquals(actual, expected);
+ }
+
+ //-----------------------------------------------------------------------
// compareTo()
//-----------------------------------------------------------------------
@Test
--- a/jdk/test/java/time/tck/java/time/TCKLocalTime.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/time/tck/java/time/TCKLocalTime.java Wed Jan 06 14:54:24 2016 +0000
@@ -2433,6 +2433,32 @@
}
}
+ //-----------------------------------------------------------------------
+ // toEpochSecond()
+ //--------------------------------------------------------------------------
+ @DataProvider(name="epochSecond")
+ Object[][] provider__toEpochSecond() {
+ return new Object[][] {
+ {LocalTime.of(0, 0).toEpochSecond(LocalDate.of(1970, 1, 1), OFFSET_PTWO), -7200L},
+ {LocalTime.of(11, 30).toEpochSecond(LocalDate.of(1965, 12, 31), OFFSET_PTWO), -126282600L},
+ {LocalTime.of(11, 30).toEpochSecond(LocalDate.of(1995, 5, 3), OFFSET_MTWO), 799507800L},
+ {LocalTime.of(0, 0).toEpochSecond(LocalDate.of(1970, 1, 1), OFFSET_PTWO),
+ Instant.ofEpochSecond(-7200).getEpochSecond()},
+ {LocalTime.of(11, 30).toEpochSecond(LocalDate.of(1969, 12, 31), OFFSET_MTWO),
+ Instant.ofEpochSecond(-37800L).getEpochSecond()},
+ {LocalTime.of(11, 30).toEpochSecond(LocalDate.of(1970, 1, 1), OFFSET_PTWO),
+ LocalDateTime.of(1970, 1, 1, 11, 30).toEpochSecond(OFFSET_PTWO)},
+ };
+ }
+
+ @Test(dataProvider="epochSecond")
+ public void test_toEpochSecond(long actual, long expected) {
+ assertEquals(actual, expected);
+ }
+
+ //-----------------------------------------------------------------------
+ // toSecondOfDay_fromNanoOfDay_symmetry()
+ //-----------------------------------------------------------------------
@Test
public void test_toSecondOfDay_fromNanoOfDay_symmetry() {
LocalTime t = LocalTime.of(0, 0);
--- a/jdk/test/java/time/tck/java/time/TCKOffsetTime.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/time/tck/java/time/TCKOffsetTime.java Wed Jan 06 14:54:24 2016 +0000
@@ -134,6 +134,7 @@
private static final ZoneId ZONE_GAZA = ZoneId.of("Asia/Gaza");
private static final ZoneOffset OFFSET_PONE = ZoneOffset.ofHours(1);
private static final ZoneOffset OFFSET_PTWO = ZoneOffset.ofHours(2);
+ private static final ZoneOffset OFFSET_MTWO = ZoneOffset.ofHours(-2);
private static final LocalDate DATE = LocalDate.of(2008, 12, 3);
private OffsetTime TEST_11_30_59_500_PONE;
@@ -1149,6 +1150,29 @@
}
//-----------------------------------------------------------------------
+ // toEpochSecond()
+ //-----------------------------------------------------------------------
+ @DataProvider(name="epochSecond")
+ Object[][] provider_toEpochSecond() {
+ return new Object[][] {
+ {OffsetTime.of(0, 0, 0, 0, OFFSET_PTWO).toEpochSecond(LocalDate.of(1970, 1, 1)), -7200L},
+ {OffsetTime.of(11, 30, 0, 0, OFFSET_MTWO).toEpochSecond(LocalDate.of(1995, 9, 27)), 812208600L},
+ {OffsetTime.of(0, 0, 0, 0, OFFSET_PONE).toEpochSecond(LocalDate.of(1970, 1, 1)),
+ Instant.ofEpochSecond(-3600).getEpochSecond()},
+ {OffsetTime.of(11, 30, 0, 0, OFFSET_PTWO).toEpochSecond(LocalDate.of(1965, 12, 31)),
+ Instant.ofEpochSecond(-126282600L).getEpochSecond()},
+ {OffsetTime.of(11, 30, 0, 0, OFFSET_MTWO).toEpochSecond(LocalDate.of(1970, 1, 1)),
+ OffsetDateTime.of(LocalDate.of(1970, 1, 1), LocalTime.of(11, 30), OFFSET_MTWO)
+ .toEpochSecond()},
+ };
+ }
+
+ @Test(dataProvider="epochSecond")
+ public void test_toEpochSecond(long actual, long expected) {
+ assertEquals(actual, expected);
+ }
+
+ //-----------------------------------------------------------------------
// compareTo()
//-----------------------------------------------------------------------
@Test
--- a/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java Wed Jan 06 14:54:24 2016 +0000
@@ -751,7 +751,7 @@
{"2012-06-30T12:30:40Z[GMT]", 2012, 6, 30, 12, 30, 40, 0, "GMT"},
{"2012-06-30T12:30:40Z[UT]", 2012, 6, 30, 12, 30, 40, 0, "UT"},
{"2012-06-30T12:30:40Z[UTC]", 2012, 6, 30, 12, 30, 40, 0, "UTC"},
- {"2012-06-30T12:30:40+01:00[Z]", 2012, 6, 30, 12, 30, 40, 0, "Z"},
+ {"2012-06-30T12:30:40+01:00[Z]", 2012, 6, 30, 11, 30, 40, 0, "Z"},
{"2012-06-30T12:30:40+01:00[+01:00]", 2012, 6, 30, 12, 30, 40, 0, "+01:00"},
{"2012-06-30T12:30:40+01:00[GMT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "GMT+01:00"},
{"2012-06-30T12:30:40+01:00[UT+01:00]", 2012, 6, 30, 12, 30, 40, 0, "UT+01:00"},
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/time/tck/java/time/format/TCKDTFParsedInstant.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+package tck.java.time.format;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * Testing DateTimeFormatter Parsing with 4 different test conditions:
+ * 1. When Zone and Offset not provided
+ * 2. When Zone and Offset provided
+ * 3. When Offset is not provided and Zone is provided
+ * 4. When Zone is not provided and Offset is provided
+ */
+
+@Test
+public class TCKDTFParsedInstant {
+
+ private static final ZoneId EUROPE_BERLIN = ZoneId.of("Europe/Berlin");
+ private static final ZoneId ASIA_ISTANBUL = ZoneId.of("Asia/Istanbul");
+
+ private DateTimeFormatter dtFormatter;
+ private ZonedDateTime zdt1, zdt2;
+ private LocalDateTime ldt1;
+ private OffsetDateTime odt1;
+
+ @BeforeMethod
+ public void setUp() throws Exception {
+ dtFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+ }
+
+ @DataProvider(name="parseWithoutZoneWithoutOffset")
+ Object[][] data_parse_WithoutOffset_WithoutZone() {
+ return new Object[][] {
+ {"1966-12-31T00:01:10", LocalDateTime.of(1966, 12, 31, 0, 1, 10)},
+ {"1970-01-01T00:00:00", LocalDateTime.of(1970, 1, 1, 0, 0, 0)},
+ {"2004-02-29T00:30:00", LocalDateTime.of(2004, 2, 29, 0, 30, 0)},
+ {"2015-12-31T23:59:59", LocalDateTime.of(2015, 12, 31, 23, 59, 59)}
+ };
+ }
+
+ @Test(dataProvider="parseWithoutZoneWithoutOffset")
+ public void testWithoutZoneWithoutOffset(String ldtString, LocalDateTime expectedLDT) {
+ dtFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
+ ldt1 = LocalDateTime.parse(ldtString, dtFormatter);
+ assertEquals(expectedLDT, ldt1);
+ }
+
+ @DataProvider(name="parseWithZoneWithOffset")
+ Object[][] data_parse_WithZone_WithOffset() {
+ return new Object[][] {
+ {"2012-10-28T01:45:00-02:30[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00-01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00-00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00+00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00+01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00+02:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+ {"2012-10-28T01:45:00+03:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 1, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00-02:30[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00-01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00-00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00+00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00+01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00+02:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+ {"2012-10-28T02:45:00+03:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00-02:30[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-02:30"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00-01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-01:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00-00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-00:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00+00:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+00:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00+01:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+01:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00+02:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+02:00"), EUROPE_BERLIN},
+ {"2012-10-28T03:45:00+03:00[Europe/Berlin]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+03:00"), EUROPE_BERLIN},
+
+ {"2012-10-28T02:45:00-02:30[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00-01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00-00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00+00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00+01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00+02:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+ {"2012-10-28T02:45:00+03:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 2, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00-02:30[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00-01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00-00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00+00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00+01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00+02:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+ {"2012-10-28T03:45:00+03:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 3, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00-02:30[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-02:30"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00-01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00-00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("-00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00+00:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+00:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00+01:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+01:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00+02:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+02:00"), ASIA_ISTANBUL},
+ {"2012-10-28T04:45:00+03:00[Asia/Istanbul]",
+ LocalDateTime.of(2012, 10, 28, 4, 45, 0, 0), ZoneOffset.of("+03:00"), ASIA_ISTANBUL}
+ };
+ }
+
+ @Test(dataProvider="parseWithZoneWithOffset")
+ public void testWithZoneWithOffset(String zdtString, LocalDateTime ldt, ZoneOffset offset, ZoneId zone) {
+ dtFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+ zdt1 = ZonedDateTime.ofInstant(ldt, offset, zone);
+ zdt2 = ZonedDateTime.parse(zdtString, dtFormatter);
+ assertEquals(zdt1, zdt2);
+ }
+
+ @DataProvider(name="parseWithZoneWithoutOffset")
+ Object[][] data_parse_WithZone_WithoutOffset() {
+ return new Object[][] {
+ {"28 Oct 00:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 0, 45, 0, 0, EUROPE_BERLIN)},
+ {"28 Oct 01:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 1, 45, 0, 0, EUROPE_BERLIN)},
+ {"28 Oct 02:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 2, 45, 0, 0, EUROPE_BERLIN)},
+ {"28 Oct 03:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 3, 45, 0, 0, EUROPE_BERLIN)},
+ {"28 Oct 04:45:00 2012 Europe/Berlin", ZonedDateTime.of(2012, 10, 28, 4, 45, 0, 0, EUROPE_BERLIN)},
+
+ {"28 Oct 01:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 1, 45, 0, 0, ASIA_ISTANBUL)},
+ {"28 Oct 02:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 2, 45, 0, 0, ASIA_ISTANBUL)},
+ {"28 Oct 03:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 3, 45, 0, 0, ASIA_ISTANBUL)},
+ {"28 Oct 04:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 4, 45, 0, 0, ASIA_ISTANBUL)},
+ {"28 Oct 05:45:00 2012 Asia/Istanbul", ZonedDateTime.of(2012, 10, 28, 5, 45, 0, 0, ASIA_ISTANBUL)}
+ };
+ }
+
+ @Test(dataProvider="parseWithZoneWithoutOffset")
+ public void testWithZoneWithoutOffset(String withZoneWithoutOffset, ZonedDateTime expectedZDT) {
+ dtFormatter = DateTimeFormatter.ofPattern("d MMM HH:mm:ss uuuu VV");
+ zdt1 = ZonedDateTime.parse(withZoneWithoutOffset, dtFormatter);
+ assertEquals(expectedZDT, zdt1);
+ }
+
+ @DataProvider(name="parseWithOffsetWithoutZone")
+ Object[][] data_parse_WithOffset_WithoutZone() {
+ return new Object[][] {
+ {"2015-12-14T00:45:00-11:30", OffsetDateTime.of(2015, 12, 14, 0, 45, 0, 0, ZoneOffset.of("-11:30"))},
+ {"2015-12-14T01:45:00-05:00", OffsetDateTime.of(2015, 12, 14, 1, 45, 0, 0, ZoneOffset.of("-05:00"))},
+ {"2015-12-14T02:45:00-00:00", OffsetDateTime.of(2015, 12, 14, 2, 45, 0, 0, ZoneOffset.of("-00:00"))},
+ {"2015-12-14T03:45:00+00:00", OffsetDateTime.of(2015, 12, 14, 3, 45, 0, 0, ZoneOffset.of("+00:00"))},
+ {"2015-12-14T04:45:00+03:30", OffsetDateTime.of(2015, 12, 14, 4, 45, 0, 0, ZoneOffset.of("+03:30"))},
+ {"2015-12-14T05:45:00+10:00", OffsetDateTime.of(2015, 12, 14, 5, 45, 0, 0, ZoneOffset.of("+10:00"))}
+ };
+ }
+
+ @Test(dataProvider="parseWithOffsetWithoutZone")
+ public void testWithOffsetWithoutZone(String odtString, OffsetDateTime expectedOTD) {
+ dtFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
+ odt1 = OffsetDateTime.parse(odtString, dtFormatter);
+ assertEquals(expectedOTD, odt1);
+ }
+}
--- a/jdk/test/java/util/Collections/AsLifoQueue.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/Collections/AsLifoQueue.java Wed Jan 06 14:54:24 2016 +0000
@@ -70,6 +70,8 @@
check(q.isEmpty());
equal(q.size(), 0);
} catch (Throwable t) { unexpected(t); }
+
+ THROWS(NullPointerException.class, () -> Collections.asLifoQueue(null));
}
//--------------------- Infrastructure ---------------------------
--- a/jdk/test/java/util/Formatter/Basic-X.java.template Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/Formatter/Basic-X.java.template Wed Jan 06 14:54:24 2016 +0000
@@ -36,7 +36,7 @@
import java.text.DateFormatSymbols;
import java.util.*;
#if[double]
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
#end[double]
import static java.util.Calendar.*;
--- a/jdk/test/java/util/Formatter/Basic.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/Formatter/Basic.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,7 +28,7 @@
* 6344623 6369500 6534606 6282094 6286592 6476425 5063507 6469160 6476168
* 8059175
*
- * @modules java.base/sun.misc
+ * @modules java.base/jdk.internal.math
* @run shell/timeout=240 Basic.sh
*/
--- a/jdk/test/java/util/Formatter/BasicDouble.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/Formatter/BasicDouble.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,7 +36,7 @@
import java.text.DateFormatSymbols;
import java.util.*;
-import sun.misc.DoubleConsts;
+import jdk.internal.math.DoubleConsts;
import static java.util.Calendar.*;
@@ -1174,6 +1174,10 @@
+
+
+
+
//---------------------------------------------------------------------
// %f - float, double, Double, BigDecimal
//---------------------------------------------------------------------
--- a/jdk/test/java/util/Map/MapFactories.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/Map/MapFactories.java Wed Jan 06 14:54:24 2016 +0000
@@ -377,4 +377,13 @@
assertEquals(sie.toString(), kvh1.toString());
}
+ // compile-time test of wildcards
+ @Test
+ public void entryWildcardTests() {
+ Map.Entry<Integer,Double> e1 = Map.entry(1, 2.0);
+ Map.Entry<Float,Long> e2 = Map.entry(3.0f, 4L);
+ Map<Number,Number> map = Map.ofEntries(e1, e2);
+ assertEquals(map.size(), 2);
+ }
+
}
--- a/jdk/test/java/util/regex/PatternStreamTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/regex/PatternStreamTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8016846 8024341 8071479
+ * @bug 8016846 8024341 8071479 8145006
* @summary Unit tests stream and lambda-based methods on Pattern and Matcher
* @library ../stream/bootlib/java.base
* @build java.util.stream.OpTestCase
@@ -42,6 +42,7 @@
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.LambdaTestHelpers;
import java.util.stream.OpTestCase;
import java.util.stream.Stream;
@@ -185,6 +186,20 @@
.exercise();
}
+ @Test
+ public void testLateBinding() {
+ Pattern pattern = Pattern.compile(",");
+
+ StringBuilder sb = new StringBuilder("a,b,c,d,e");
+ Stream<String> stream = pattern.splitAsStream(sb);
+ sb.setLength(3);
+ assertEquals(Arrays.asList("a", "b"), stream.collect(Collectors.toList()));
+
+ stream = pattern.splitAsStream(sb);
+ sb.append(",f,g");
+ assertEquals(Arrays.asList("a", "b", "f", "g"), stream.collect(Collectors.toList()));
+ }
+
public void testFailfastMatchResults() {
Pattern p = Pattern.compile("X");
Matcher m = p.matcher("XX");
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -56,6 +56,7 @@
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.flatMapping;
+import static java.util.stream.Collectors.filtering;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.groupingByConcurrent;
import static java.util.stream.Collectors.mapping;
@@ -72,7 +73,7 @@
/*
* @test
- * @bug 8071600
+ * @bug 8071600 8144675
* @summary Test for collectors.
*/
public class CollectorsTest extends OpTestCase {
@@ -118,6 +119,23 @@
}
}
+ static class FilteringAssertion<T, R> extends CollectorAssertion<T, R> {
+ private final Predicate<T> filter;
+ private final CollectorAssertion<T, R> downstream;
+
+ public FilteringAssertion(Predicate<T> filter, CollectorAssertion<T, R> downstream) {
+ this.filter = filter;
+ this.downstream = downstream;
+ }
+
+ @Override
+ void assertValue(R value, Supplier<Stream<T>> source, boolean ordered) throws ReflectiveOperationException {
+ downstream.assertValue(value,
+ () -> source.get().filter(filter),
+ ordered);
+ }
+ }
+
static class GroupingByAssertion<T, K, V, M extends Map<K, ? extends V>> extends CollectorAssertion<T, M> {
private final Class<? extends Map> clazz;
private final Function<T, K> classifier;
@@ -551,6 +569,36 @@
}
@Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
+ public void testGroupingByWithFiltering(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
+ Function<Integer, Integer> classifier = i -> i % 3;
+ Predicate<Integer> filteringByMod2 = i -> i % 2 == 0;
+ Predicate<Integer> filteringByUnder100 = i -> i % 2 < 100;
+ Predicate<Integer> filteringByTrue = i -> true;
+ Predicate<Integer> filteringByFalse = i -> false;
+
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByMod2, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByMod2,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByUnder100, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByUnder100,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByTrue, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByTrue,
+ new ToListAssertion<>())));
+ exerciseMapCollection(data,
+ groupingBy(classifier, filtering(filteringByFalse, toList())),
+ new GroupingByAssertion<>(classifier, HashMap.class,
+ new FilteringAssertion<>(filteringByFalse,
+ new ToListAssertion<>())));
+ }
+
+ @Test(dataProvider = "StreamTestData<Integer>", dataProviderClass = StreamTestDataProvider.class)
public void testTwoLevelGroupingBy(String name, TestData.OfRef<Integer> data) throws ReflectiveOperationException {
Function<Integer, Integer> classifier = i -> i % 6;
Function<Integer, Integer> classifier2 = i -> i % 23;
--- a/jdk/test/java/util/zip/TestZipError.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/zip/TestZipError.java Wed Jan 06 14:54:24 2016 +0000
@@ -84,9 +84,10 @@
try {
while (entries.hasMoreElements()) {
ze = entries.nextElement();
+ zf.getInputStream(ze).readAllBytes();
}
fail("Did not get expected exception");
- } catch (ZipError e) {
+ } catch (ZipException e) {
pass();
} catch (InternalError e) {
fail("Caught InternalError instead of expected ZipError");
--- a/jdk/test/java/util/zip/ZipFile/ReadZip.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/java/util/zip/ZipFile/ReadZip.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,6 +30,7 @@
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
+import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.zip.*;
@@ -110,6 +111,6 @@
"input"
+ String.valueOf(new java.util.Random().nextInt())
+ ".zip")));
- } catch (FileNotFoundException fnfe) {}
+ } catch (NoSuchFileException nsfe) {}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/zip/ZipFile/TestZipFile.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,361 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8142508
+ * @summary Tests various ZipFile apis
+ * @run main/manual TestZipFile
+ */
+
+import java.io.*;
+import java.lang.reflect.Method;
+import java.nio.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.zip.*;
+
+public class TestZipFile {
+
+ private static Random r = new Random();
+ private static int N = 50;
+ private static int NN = 10;
+ private static int ENUM = 10000;
+ private static int ESZ = 10000;
+ private static ExecutorService executor = Executors.newFixedThreadPool(20);
+ private static Set<Path> paths = new HashSet<>();
+
+ static void realMain (String[] args) throws Throwable {
+
+ try {
+ for (int i = 0; i < N; i++) {
+ test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ test(r.nextInt(ENUM), r.nextInt(ESZ), true, true);
+ }
+
+ for (int i = 0; i < NN; i++) {
+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), false, true);
+ test(r.nextInt(ENUM), 100000 + r.nextInt(ESZ), true, true);
+ testCachedDelete();
+ testCachedOverwrite();
+ //test(r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ }
+
+ test(70000, 1000, false, true); // > 65536 entry number;
+ testDelete(); // OPEN_DELETE
+
+ executor.shutdown();
+ executor.awaitTermination(10, TimeUnit.MINUTES);
+ } finally {
+ for (Path path : paths) {
+ Files.deleteIfExists(path);
+ }
+ }
+ }
+
+ static void test(int numEntry, int szMax, boolean addPrefix, boolean cleanOld) {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip = new Zip(name, numEntry, szMax, addPrefix, cleanOld);
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip));
+ }
+ }
+
+ // test scenario:
+ // (1) open the ZipFile(zip) with OPEN_READ | OPEN_DELETE
+ // (2) test the ZipFile works correctly
+ // (3) check the zip is deleted after ZipFile gets closed
+ static void testDelete() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ try (ZipFile zf = new ZipFile(new File(zip.name),
+ ZipFile.OPEN_READ | ZipFile.OPEN_DELETE ))
+ {
+ doTest0(zip, zf);
+ }
+ Path p = Paths.get(name);
+ if (Files.exists(p)) {
+ fail("Failed to delete " + name + " with OPEN_DELETE");
+ }
+ }
+
+ // test scenario:
+ // (1) keep a ZipFile(zip1) alive (in ZipFile's cache), dont close it
+ // (2) delete zip1 and create zip2 with the same name the zip1 with zip2
+ // (3) zip1 tests should fail, but no crash
+ // (4) zip2 tasks should all get zip2, then pass normal testing.
+ static void testCachedDelete() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+
+ try (ZipFile zf = new ZipFile(zip1.name)) {
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> verifyNoCrash(zip1));
+ }
+ // delete the "zip1" and create a new one to test
+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ /*
+ System.out.println("========================================");
+ System.out.printf(" zip1=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n",
+ zip1.name, zip1.lastModified, zip1.entries.size(),
+ zip1.attrs.fileKey(), zip1.attrs.size(), zip1.attrs.lastModifiedTime().toMillis());
+ System.out.printf(" zip2=%s, mt=%d, enum=%d%n ->attrs=[key=%s, sz=%d, mt=%d]%n",
+ zip2.name, zip2.lastModified, zip2.entries.size(),
+ zip2.attrs.fileKey(), zip2.attrs.size(), zip2.attrs.lastModifiedTime().toMillis());
+ */
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip2));
+ }
+ }
+ }
+
+ // overwrite the "zip1" and create a new one to test. So the two zip files
+ // have the same fileKey, but probably different lastModified()
+ static void testCachedOverwrite() throws Throwable {
+ String name = "zftest" + r.nextInt() + ".zip";
+ Zip zip1 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, true);
+ try (ZipFile zf = new ZipFile(zip1.name)) {
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> verifyNoCrash(zip1));
+ }
+ // overwrite the "zip1" with new contents
+ Zip zip2 = new Zip(name, r.nextInt(ENUM), r.nextInt(ESZ), false, false);
+ for (int i = 0; i < NN; i++) {
+ executor.submit(() -> doTest(zip2));
+ }
+ }
+ }
+
+ // just check the entries and contents. since the file has been either overwritten
+ // or deleted/rewritten, we only care if it crahes or not.
+ static void verifyNoCrash(Zip zip) throws RuntimeException {
+ try (ZipFile zf = new ZipFile(zip.name)) {
+ List<ZipEntry> zlist = new ArrayList(zip.entries.keySet());
+ String[] elist = zf.stream().map( e -> e.getName()).toArray(String[]::new);
+ if (!Arrays.equals(elist,
+ zlist.stream().map( e -> e.getName()).toArray(String[]::new)))
+ {
+ //System.out.printf("++++++ LIST NG [%s] entries.len=%d, expected=%d+++++++%n",
+ // zf.getName(), elist.length, zlist.size());
+ return;
+ }
+ for (ZipEntry ze : zlist) {
+ byte[] zdata = zip.entries.get(ze);
+ ZipEntry e = zf.getEntry(ze.getName());
+ if (e != null) {
+ checkEqual(e, ze);
+ if (!e.isDirectory()) {
+ // check with readAllBytes
+ try (InputStream is = zf.getInputStream(e)) {
+ if (!Arrays.equals(zdata, is.readAllBytes())) {
+ //System.out.printf("++++++ BYTES NG [%s]/[%s] ++++++++%n",
+ // zf.getName(), ze.getName());
+ }
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ // t.printStackTrace();
+ // fail(t.toString());
+ }
+ }
+
+ static void checkEqual(ZipEntry x, ZipEntry y) {
+ if (x.getName().equals(y.getName()) &&
+ x.isDirectory() == y.isDirectory() &&
+ x.getMethod() == y.getMethod() &&
+ (x.getTime() / 2000) == y.getTime() / 2000 &&
+ x.getSize() == y.getSize() &&
+ x.getCompressedSize() == y.getCompressedSize() &&
+ x.getCrc() == y.getCrc() &&
+ x.getComment().equals(y.getComment())
+ ) {
+ pass();
+ } else {
+ fail(x + " not equal to " + y);
+ System.out.printf(" %s %s%n", x.getName(), y.getName());
+ System.out.printf(" %d %d%n", x.getMethod(), y.getMethod());
+ System.out.printf(" %d %d%n", x.getTime(), y.getTime());
+ System.out.printf(" %d %d%n", x.getSize(), y.getSize());
+ System.out.printf(" %d %d%n", x.getCompressedSize(), y.getCompressedSize());
+ System.out.printf(" %d %d%n", x.getCrc(), y.getCrc());
+ System.out.println("-----------------");
+ }
+ }
+
+ static void doTest(Zip zip) throws RuntimeException {
+ //Thread me = Thread.currentThread();
+ try (ZipFile zf = new ZipFile(zip.name)) {
+ doTest0(zip, zf);
+ } catch (Throwable t) {
+ throw new RuntimeException(t);
+ }
+ }
+
+ static void doTest0(Zip zip, ZipFile zf) throws Throwable {
+ List<ZipEntry> list = new ArrayList(zip.entries.keySet());
+ // (1) check entry list, in expected order
+ if (!check(Arrays.equals(
+ list.stream().map( e -> e.getName()).toArray(String[]::new),
+ zf.stream().map( e -> e.getName()).toArray(String[]::new)))) {
+ return;
+ }
+ // (2) shuffle, and check each entry and its bytes
+ Collections.shuffle(list);
+ for (ZipEntry ze : list) {
+ byte[] data = zip.entries.get(ze);
+ ZipEntry e = zf.getEntry(ze.getName());
+ checkEqual(e, ze);
+ if (!e.isDirectory()) {
+ // check with readAllBytes
+ try (InputStream is = zf.getInputStream(e)) {
+ check(Arrays.equals(data, is.readAllBytes()));
+ }
+ // check with smaller sized buf
+ try (InputStream is = zf.getInputStream(e)) {
+ byte[] buf = new byte[(int)e.getSize()];
+ int sz = r.nextInt((int)e.getSize()/4 + 1) + 1;
+ int off = 0;
+ int n;
+ while ((n = is.read(buf, off, buf.length - off)) > 0) {
+ off += n;
+ }
+ check(is.read() == -1);
+ check(Arrays.equals(data, buf));
+ }
+ }
+ }
+ // (3) check getMetaInfEntryNames
+ String[] metas = list.stream()
+ .map( e -> e.getName())
+ .filter( s -> s.startsWith("META-INF/"))
+ .sorted()
+ .toArray(String[]::new);
+ if (metas.length > 0) {
+ // meta-inf entries
+ Method getMetas = ZipFile.class.getDeclaredMethod("getMetaInfEntryNames");
+ getMetas.setAccessible(true);
+ String[] names = (String[])getMetas.invoke(zf);
+ if (names == null) {
+ fail("Failed to get metanames from " + zf);
+ } else {
+ Arrays.sort(names);
+ check(Arrays.equals(names, metas));
+ }
+ }
+ }
+
+ private static class Zip {
+ String name;
+ Map<ZipEntry, byte[]> entries;
+ BasicFileAttributes attrs;
+ long lastModified;
+
+ Zip(String name, int num, int szMax, boolean prefix, boolean clean) {
+ this.name = name;
+ entries = new LinkedHashMap<>(num);
+ try {
+ Path p = Paths.get(name);
+ if (clean) {
+ Files.deleteIfExists(p);
+ }
+ paths.add(p);
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+
+ try (FileOutputStream fos = new FileOutputStream(name);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ ZipOutputStream zos = new ZipOutputStream(bos))
+ {
+ if (prefix) {
+ byte[] bytes = new byte[r.nextInt(1000)];
+ r.nextBytes(bytes);
+ bos.write(bytes);
+ }
+ CRC32 crc = new CRC32();
+ for (int i = 0; i < num; i++) {
+ String ename = "entry-" + i + "-name-" + r.nextLong();
+ ZipEntry ze = new ZipEntry(ename);
+ int method = r.nextBoolean() ? ZipEntry.STORED : ZipEntry.DEFLATED;
+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
+ }
+ // add some manifest entries
+ for (int i = 0; i < r.nextInt(20); i++) {
+ String meta = "META-INF/" + "entry-" + i + "-metainf-" + r.nextLong();
+ ZipEntry ze = new ZipEntry(meta);
+ writeEntry(zos, crc, ze, ZipEntry.STORED, szMax);
+ }
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+ try {
+ this.attrs = Files.readAttributes(Paths.get(name), BasicFileAttributes.class);
+ this.lastModified = new File(name).lastModified();
+ } catch (Exception x) {
+ throw (RuntimeException)x;
+ }
+ }
+
+ private void writeEntry(ZipOutputStream zos, CRC32 crc,
+ ZipEntry ze, int method, int szMax)
+ throws IOException
+ {
+ ze.setMethod(method);
+ byte[] data = new byte[r.nextInt(szMax + 1)];
+ r.nextBytes(data);
+ if (method == ZipEntry.STORED) { // must set size/csize/crc
+ ze.setSize(data.length);
+ ze.setCompressedSize(data.length);
+ crc.reset();
+ crc.update(data);
+ ze.setCrc(crc.getValue());
+ }
+ ze.setTime(System.currentTimeMillis());
+ ze.setComment(ze.getName());
+ zos.putNextEntry(ze);
+ zos.write(data);
+ zos.closeEntry();
+ entries.put(ze, data);
+ }
+ }
+
+ //--------------------- Infrastructure ---------------------------
+ static volatile int passed = 0, failed = 0;
+ static void pass() {passed++;}
+ static void pass(String msg) {System.out.println(msg); passed++;}
+ static void fail() {failed++; Thread.dumpStack();}
+ static void fail(String msg) {System.out.println(msg); fail();}
+ static void unexpected(Throwable t) {failed++; t.printStackTrace();}
+ static void unexpected(Throwable t, String msg) {
+ System.out.println(msg); failed++; t.printStackTrace();}
+ static boolean check(boolean cond) {if (cond) pass(); else fail(); return cond;}
+
+ public static void main(String[] args) throws Throwable {
+ try {realMain(args);} catch (Throwable t) {unexpected(t);}
+ System.out.println("\nPassed = " + passed + " failed = " + failed);
+ if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/jpeg/JpegImageColorSpaceTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8041501
+ * @summary Test verifies if there is no JFIF & EXIF header
+ * and sampling factor is same of JPEG image, then
+ * imageIO should not override colorspace determined
+ * in IJG library.
+ * @run main JpegImageColorSpaceTest
+ */
+
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import javax.imageio.ImageIO;
+
+public class JpegImageColorSpaceTest {
+
+ public static void main(String args[]) throws Exception {
+
+ String fileName = "nomarkers.jpg";
+ String sep = System.getProperty("file.separator");
+ String dir = System.getProperty("test.src", ".");
+ String filePath = dir+sep+fileName;
+ System.out.println("Test file: " + filePath);
+ File imageFile = new File(filePath);
+
+ BufferedImage bufferedImage = ImageIO.read(imageFile);
+ int imageWidth = bufferedImage.getWidth();
+ int imageHeight = bufferedImage.getHeight();
+
+ for (int i = 0; i < imageWidth; i++) {
+ for(int j = 0; j < imageHeight; j++) {
+ /*
+ * Since image is white we check individual pixel values from
+ * BufferedImage to verify if ImageIO.read() is done with proper
+ * color space or not.
+ */
+ if (bufferedImage.getRGB(i, j) != Color.white.getRGB()) {
+ // color space is not proper
+ throw new RuntimeException("ColorSpace is not determined "
+ + "properly by ImageIO");
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/jpeg/JpegMetadataColorSpaceTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 8074967
+ * @summary Test verifies if there is no JFIF & EXIF header
+ * and sampling factor is same of JPEG image, then
+ * JPEG colorspace should not be RGB.
+ * @run main JpegMetadataColorSpaceTest
+ */
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.metadata.IIOMetadataNode;
+import javax.imageio.stream.ImageInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
+public class JpegMetadataColorSpaceTest {
+ public static void main(String[] args) throws IOException {
+ String fileName = "nomarkers.jpg";
+ String sep = System.getProperty("file.separator");
+ String dir = System.getProperty("test.src", ".");
+ String filePath = dir+sep+fileName;
+ System.out.println("Test file: " + filePath);
+ File file = new File(filePath);
+ ImageInputStream stream = ImageIO.createImageInputStream(file);
+ Iterator<ImageReader> readers = ImageIO.getImageReaders(stream);
+
+ if(readers.hasNext()) {
+ ImageReader reader = readers.next();
+ reader.setInput(stream);
+ IIOMetadata metadata = reader.getImageMetadata(0);
+
+ IIOMetadataNode standardTree = (IIOMetadataNode)
+ metadata.getAsTree
+ (IIOMetadataFormatImpl.standardMetadataFormatName);
+ IIOMetadataNode colorSpaceType = (IIOMetadataNode)
+ standardTree.getElementsByTagName("ColorSpaceType").item(0);
+ String colorSpaceName = colorSpaceType.getAttribute("name");
+ if(colorSpaceName.equals("RGB"))
+ throw new RuntimeException("Identified incorrect ColorSpace");
+ }
+ }
+}
Binary file jdk/test/javax/imageio/plugins/jpeg/nomarkers.jpg has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/png/PngForceStopWritingTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6967419
+ * @summary Test verifies that when we force stop PNG writing to
+ * ImageOutputStream, it should not cause IndexOutOfBoundException.
+ * @run main PngForceStopWritingTest
+ */
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.imageio.ImageIO;
+import javax.imageio.stream.ImageOutputStream;
+
+public class PngForceStopWritingTest {
+
+ public static void main(String[] args) throws IOException {
+
+ OutputStream outputStream = new NullOutputStream();
+ ImageOutputStream imageOutputStream =
+ ImageIO.createImageOutputStream(outputStream);
+ try {
+ ImageIO.write(createImage(2048),"PNG", imageOutputStream);
+ } catch (IOException e) {
+ imageOutputStream.close();
+ }
+ }
+
+ private static BufferedImage createImage(int size) {
+
+ BufferedImage image = new
+ BufferedImage(size, size, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = image.createGraphics();
+ g.setPaint(new GradientPaint(0, 0, Color.blue, size, size, Color.red));
+ g.fillRect(0, 0, size, size);
+ g.dispose();
+ return image;
+ }
+
+ static class NullOutputStream extends OutputStream {
+ long count = 0;
+ @Override
+ public void write(int b) throws IOException {
+ count++;
+ if (count > 30000L) {
+ throw new IOException("Force stop image writing");
+ }
+ }
+ }
+}
--- a/jdk/test/javax/imageio/plugins/shared/WriteAfterAbort.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/imageio/plugins/shared/WriteAfterAbort.java Wed Jan 06 14:54:24 2016 +0000
@@ -130,13 +130,25 @@
ImageWriterSpi.class, provider -> true, true);
// Validates all supported ImageWriters
+ int numFailures = 0;
while (iter.hasNext()) {
final WriteAfterAbort writeAfterAbort = new WriteAfterAbort();
final ImageWriter writer = iter.next().createWriterInstance();
System.out.println("ImageWriter = " + writer);
- writeAfterAbort.test(writer);
+ try {
+ writeAfterAbort.test(writer);
+ } catch (Exception e) {
+ System.err.println("Test failed for \""
+ + writer.getOriginatingProvider().getFormatNames()[0]
+ + "\" format.");
+ numFailures++;
+ }
}
- System.out.println("Test passed");
+ if (numFailures == 0) {
+ System.out.println("Test passed.");
+ } else {
+ throw new RuntimeException("Test failed.");
+ }
}
// Callbacks
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/plugins/tiff/WriteToSequenceAfterAbort.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,376 @@
+/*
+ * 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.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriter;
+import javax.imageio.event.IIOWriteProgressListener;
+import javax.imageio.stream.ImageOutputStream;
+
+import static java.awt.image.BufferedImage.TYPE_BYTE_BINARY;
+import java.awt.image.ColorModel;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SampleModel;
+import java.awt.image.WritableRaster;
+import java.util.Vector;
+import javax.imageio.IIOImage;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+
+/**
+ * @test
+ * @bug 8144245
+ * @summary Ensure aborting write works properly for a TIFF sequence.
+ */
+public final class WriteToSequenceAfterAbort implements IIOWriteProgressListener {
+
+ private volatile boolean abortFlag = true;
+ private volatile boolean isAbortCalled;
+ private volatile boolean isCompleteCalled;
+ private volatile boolean isProgressCalled;
+ private volatile boolean isStartedCalled;
+ private static final int WIDTH = 100;
+ private static final int HEIGHT = 100;
+ private static final int NUM_TILES_XY = 3;
+
+ private class TiledImage implements RenderedImage {
+ private final BufferedImage tile;
+ private final BufferedImage image;
+ private final int numXTiles, numYTiles;
+ private boolean isImageInitialized = false;
+
+ TiledImage(BufferedImage tile, int numXTiles, int numYTiles) {
+ this.tile = tile;
+ this.numXTiles = numXTiles;
+ this.numYTiles = numYTiles;
+ image = new BufferedImage(getWidth(), getHeight(), tile.getType());
+ }
+
+ @Override
+ public Vector<RenderedImage> getSources() {
+ return null;
+ }
+
+ @Override
+ public Object getProperty(String string) {
+ return java.awt.Image.UndefinedProperty;
+ }
+
+ @Override
+ public String[] getPropertyNames() {
+ return new String[0];
+ }
+
+ @Override
+ public ColorModel getColorModel() {
+ return tile.getColorModel();
+ }
+
+ @Override
+ public SampleModel getSampleModel() {
+ return tile.getSampleModel();
+ }
+
+ @Override
+ public int getWidth() {
+ return numXTiles*tile.getWidth();
+ }
+
+ @Override
+ public int getHeight() {
+ return numYTiles*tile.getHeight();
+ }
+
+ @Override
+ public int getMinX() {
+ return 0;
+ }
+
+ @Override
+ public int getMinY() {
+ return 0;
+ }
+
+ @Override
+ public int getNumXTiles() {
+ return numXTiles;
+ }
+
+ @Override
+ public int getNumYTiles() {
+ return numYTiles;
+ }
+
+ @Override
+ public int getMinTileX() {
+ return 0;
+ }
+
+ @Override
+ public int getMinTileY() {
+ return 0;
+ }
+
+ @Override
+ public int getTileWidth() {
+ return tile.getWidth();
+ }
+
+ @Override
+ public int getTileHeight() {
+ return tile.getHeight();
+ }
+
+ @Override
+ public int getTileGridXOffset() {
+ return 0;
+ }
+
+ @Override
+ public int getTileGridYOffset() {
+ return 0;
+ }
+
+ @Override
+ public Raster getTile(int x, int y) {
+ WritableRaster r = tile.getRaster();
+ return r.createWritableTranslatedChild(x*tile.getWidth(),
+ y*tile.getHeight());
+ }
+
+ @Override
+ public Raster getData() {
+ return getAsBufferedImage().getData();
+ }
+
+ @Override
+ public Raster getData(Rectangle r) {
+ return getAsBufferedImage().getData(r);
+ }
+
+ @Override
+ public WritableRaster copyData(WritableRaster wr) {
+ return getAsBufferedImage().copyData(wr);
+ }
+
+ public BufferedImage getAsBufferedImage() {
+ synchronized (image) {
+ if (!isImageInitialized) {
+ int tx0 = getMinTileX(), ty0 = getMinTileY();
+ int txN = tx0 + getNumXTiles(), tyN = ty0 + getNumYTiles();
+ for (int j = ty0; j < tyN; j++) {
+ for (int i = tx0; i < txN; i++) {
+ image.setData(getTile(i, j));
+ }
+ }
+ }
+ isImageInitialized = true;
+ }
+ return image;
+ }
+ }
+
+ private void test(final ImageWriter writer) throws IOException {
+ String suffix = writer.getOriginatingProvider().getFileSuffixes()[0];
+
+ // Image initialization
+ BufferedImage imageUpperLeft =
+ new BufferedImage(WIDTH, HEIGHT, TYPE_BYTE_BINARY);
+ Graphics2D g = imageUpperLeft.createGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, WIDTH/2, HEIGHT/2);
+ g.dispose();
+ BufferedImage imageLowerRight =
+ new BufferedImage(WIDTH, HEIGHT, TYPE_BYTE_BINARY);
+ g = imageLowerRight.createGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(WIDTH/2, HEIGHT/2, WIDTH/2, HEIGHT/2);
+ g.dispose();
+ TiledImage[] images = new TiledImage[] {
+ new TiledImage(imageUpperLeft, NUM_TILES_XY, NUM_TILES_XY),
+ new TiledImage(imageUpperLeft, NUM_TILES_XY, NUM_TILES_XY),
+ new TiledImage(imageLowerRight, NUM_TILES_XY, NUM_TILES_XY),
+ new TiledImage(imageLowerRight, NUM_TILES_XY, NUM_TILES_XY)
+ };
+
+ // File initialization
+ File file = File.createTempFile("temp", "." + suffix);
+ file.deleteOnExit();
+ FileOutputStream fos = new SkipWriteOnAbortOutputStream(file);
+ ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
+ writer.setOutput(ios);
+ writer.addIIOWriteProgressListener(this);
+
+ writer.prepareWriteSequence(null);
+ boolean[] abortions = new boolean[] {true, false, true, false};
+ for (int i = 0; i < 4; i++) {
+ abortFlag = abortions[i];
+ isAbortCalled = false;
+ isCompleteCalled = false;
+ isProgressCalled = false;
+ isStartedCalled = false;
+
+ TiledImage image = images[i];
+ if (abortFlag) {
+ // This write will be aborted, and file will not be touched
+ writer.writeToSequence(new IIOImage(image, null, null), null);
+ if (!isStartedCalled) {
+ throw new RuntimeException("Started should be called");
+ }
+ if (!isProgressCalled) {
+ throw new RuntimeException("Progress should be called");
+ }
+ if (!isAbortCalled) {
+ throw new RuntimeException("Abort should be called");
+ }
+ if (isCompleteCalled) {
+ throw new RuntimeException("Complete should not be called");
+ }
+ } else {
+ // This write should be completed successfully and the file should
+ // contain correct image data.
+ writer.writeToSequence(new IIOImage(image, null, null), null);
+ if (!isStartedCalled) {
+ throw new RuntimeException("Started should be called");
+ }
+ if (!isProgressCalled) {
+ throw new RuntimeException("Progress should be called");
+ }
+ if (isAbortCalled) {
+ throw new RuntimeException("Abort should not be called");
+ }
+ if (!isCompleteCalled) {
+ throw new RuntimeException("Complete should be called");
+ }
+ }
+ }
+
+ writer.endWriteSequence();
+ writer.dispose();
+ ios.close();
+
+ // Validates content of the file.
+ ImageReader reader = ImageIO.getImageReader(writer);
+ ImageInputStream iis = ImageIO.createImageInputStream(file);
+ reader.setInput(iis);
+ for (int i = 0; i < 2; i++) {
+ System.out.println("Testing image " + i);
+ BufferedImage imageRead = reader.read(i);
+ BufferedImage imageWrite = images[2 * i].getAsBufferedImage();
+ for (int x = 0; x < WIDTH; ++x) {
+ for (int y = 0; y < HEIGHT; ++y) {
+ if (imageRead.getRGB(x, y) != imageWrite.getRGB(x, y)) {
+ throw new RuntimeException("Test failed for image " + i);
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(final String[] args) throws IOException {
+ WriteToSequenceAfterAbort writeAfterAbort = new WriteToSequenceAfterAbort();
+ ImageWriter writer = ImageIO.getImageWritersByFormatName("TIFF").next();
+ writeAfterAbort.test(writer);
+ System.out.println("Test passed.");
+ }
+
+ // Callbacks
+
+ @Override
+ public void imageComplete(ImageWriter source) {
+ isCompleteCalled = true;
+ }
+
+ @Override
+ public void imageProgress(ImageWriter source, float percentageDone) {
+ isProgressCalled = true;
+ if (percentageDone > 50 && abortFlag) {
+ source.abort();
+ }
+ }
+
+ @Override
+ public void imageStarted(ImageWriter source, int imageIndex) {
+ isStartedCalled = true;
+ }
+
+ @Override
+ public void writeAborted(final ImageWriter source) {
+ isAbortCalled = true;
+ }
+
+ @Override
+ public void thumbnailComplete(ImageWriter source) {
+ }
+
+ @Override
+ public void thumbnailProgress(ImageWriter source, float percentageDone) {
+ }
+
+ @Override
+ public void thumbnailStarted(ImageWriter source, int imageIndex,
+ int thumbnailIndex) {
+ }
+
+ /**
+ * We need to skip writes on abort, because content of the file after abort
+ * is undefined.
+ */
+ private class SkipWriteOnAbortOutputStream extends FileOutputStream {
+
+ SkipWriteOnAbortOutputStream(File file) throws FileNotFoundException {
+ super(file);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ if (!abortFlag) {
+ super.write(b);
+ }
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ if (!abortFlag) {
+ super.write(b);
+ }
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (!abortFlag) {
+ super.write(b, off, len);
+ }
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/spi/MarkTryFinallyReproducer.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,367 @@
+/*
+ * Copyright 2015 Red Hat, Inc.
+ * 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 8144071
+ * @run main/othervm MarkTryFinallyReproducer
+ * @summary Test that call to canDecodeInput in ImageIO don't corrupt
+ * mark/reset stack in ImageInputStream
+ * @author Jiri Vanek
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.ByteOrder;
+import java.util.Locale;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.spi.IIORegistry;
+import javax.imageio.spi.ImageReaderSpi;
+import javax.imageio.stream.IIOByteBuffer;
+import javax.imageio.stream.ImageInputStream;
+
+
+public class MarkTryFinallyReproducer {
+
+ private static final byte[] bmp = new byte[]{
+ 127,127, 66, 77, -86, 0, 0, 0, 0, 0, 0, 0,
+ 122, 0, 0, 0, 108, 0, 0, 0, 4, 0, 0, 0, 4,
+ 0, 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 48, 0, 0,
+ 0, 19, 11, 0, 0, 19, 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 66, 71, 82, 115, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, -1, -1, -1,
+ -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, 0, 0, -17,
+ 0, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, -1, -1, -1,
+ -1, 0, 0, 0, -1, -1, -1, -1, -1, -1, 0, 0, -1
+ };
+ //first two are evil, we are skipping them later. Others are normal BMP
+
+ private static class NotClosingImageInputStream implements ImageInputStream {
+
+ private final ImageInputStream src;
+
+ private NotClosingImageInputStream(ImageInputStream createImageInputStream) {
+ this.src = createImageInputStream;
+ }
+
+ @Override
+ public void setByteOrder(ByteOrder byteOrder) {
+ src.setByteOrder(byteOrder);
+ }
+
+ @Override
+ public ByteOrder getByteOrder() {
+ return src.getByteOrder();
+ }
+
+ @Override
+ public int read() throws IOException {
+ return src.read();
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return src.read(b);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return src.read(b, off, len);
+ }
+
+ @Override
+ public void readBytes(IIOByteBuffer buf, int len) throws IOException {
+ src.readBytes(buf, len);
+ }
+
+ @Override
+ public boolean readBoolean() throws IOException {
+ return src.readBoolean();
+ }
+
+ @Override
+ public byte readByte() throws IOException {
+ return src.readByte();
+ }
+
+ @Override
+ public int readUnsignedByte() throws IOException {
+ return src.readUnsignedByte();
+ }
+
+ @Override
+ public short readShort() throws IOException {
+ return src.readShort();
+ }
+
+ @Override
+ public int readUnsignedShort() throws IOException {
+ return src.readUnsignedShort();
+ }
+
+ @Override
+ public char readChar() throws IOException {
+ return src.readChar();
+ }
+
+ @Override
+ public int readInt() throws IOException {
+ return src.readInt();
+ }
+
+ @Override
+ public long readUnsignedInt() throws IOException {
+ return src.readUnsignedInt();
+ }
+
+ @Override
+ public long readLong() throws IOException {
+ return src.readLong();
+ }
+
+ @Override
+ public float readFloat() throws IOException {
+ return src.readFloat();
+ }
+
+ @Override
+ public double readDouble() throws IOException {
+ return src.readDouble();
+ }
+
+ @Override
+ public String readLine() throws IOException {
+ return src.readLine();
+ }
+
+ @Override
+ public String readUTF() throws IOException {
+ return src.readUTF();
+ }
+
+ @Override
+ public void readFully(byte[] b, int off, int len) throws IOException {
+ src.readFully(b, off, len);
+ }
+
+ @Override
+ public void readFully(byte[] b) throws IOException {
+ src.readFully(b);
+ }
+
+ @Override
+ public void readFully(short[] s, int off, int len) throws IOException {
+ src.readFully(s, off, len);
+ }
+
+ @Override
+ public void readFully(char[] c, int off, int len) throws IOException {
+ src.readFully(c, off, len);
+ }
+
+ @Override
+ public void readFully(int[] i, int off, int len) throws IOException {
+ src.readFully(i, off, len);
+ }
+
+ @Override
+ public void readFully(long[] l, int off, int len) throws IOException {
+ src.readFully(l, off, len);
+ }
+
+ @Override
+ public void readFully(float[] f, int off, int len) throws IOException {
+ src.readFully(f, off, len);
+ }
+
+ @Override
+ public void readFully(double[] d, int off, int len) throws IOException {
+ src.readFully(d, off, len);
+ }
+
+ @Override
+ public long getStreamPosition() throws IOException {
+ return src.getStreamPosition();
+ }
+
+ @Override
+ public int getBitOffset() throws IOException {
+ return src.getBitOffset();
+ }
+
+ @Override
+ public void setBitOffset(int bitOffset) throws IOException {
+ src.setBitOffset(bitOffset);
+ }
+
+ @Override
+ public int readBit() throws IOException {
+ return src.readBit();
+ }
+
+ @Override
+ public long readBits(int numBits) throws IOException {
+ return src.readBits(numBits);
+ }
+
+ @Override
+ public long length() throws IOException {
+ return src.length();
+ }
+
+ @Override
+ public int skipBytes(int n) throws IOException {
+ return src.skipBytes(n);
+ }
+
+ @Override
+ public long skipBytes(long n) throws IOException {
+ return src.skipBytes(n);
+ }
+
+ @Override
+ public void seek(long pos) throws IOException {
+ src.seek(pos);
+ }
+
+ @Override
+ public void mark() {
+ src.mark();
+ }
+
+ @Override
+ public void reset() throws IOException {
+ src.reset();
+ }
+
+ @Override
+ public void flushBefore(long pos) throws IOException {
+ src.flushBefore(pos);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ src.flush();
+ }
+
+ @Override
+ public long getFlushedPosition() {
+ return src.getFlushedPosition();
+ }
+
+ @Override
+ public boolean isCached() {
+ return src.isCached();
+ }
+
+ @Override
+ public boolean isCachedMemory() {
+ return src.isCachedMemory();
+ }
+
+ @Override
+ public boolean isCachedFile() {
+ return src.isCachedFile();
+ }
+
+ @Override
+ public void close() throws IOException {
+ //the only important one. nothing
+ }
+ }
+
+ static final String readerClassName
+ = MarkTryFinallyReproducerSpi.class.getName();
+ static final String[] localNames = {"myNames"};
+ static final String[] localSuffixes = {"mySuffixes"};
+ static final String[] localMIMETypes = {"myMimes"};
+
+ public static class MarkTryFinallyReproducerSpi extends ImageReaderSpi {
+
+ public MarkTryFinallyReproducerSpi() {
+ super("MarkTryFinallyReproducerSpi",
+ "1.0",
+ localNames,
+ localSuffixes,
+ localMIMETypes,
+ readerClassName,
+ new Class[]{ImageInputStream.class},
+ new String[0],
+ false,
+ null,
+ null,
+ new String[0],
+ new String[0],
+ false,
+ null,
+ null,
+ new String[0],
+ new String[0]);
+ }
+
+ @Override
+ public String getDescription(Locale locale) {
+ return "";
+ }
+
+ @Override
+ public boolean canDecodeInput(Object input) throws IOException {
+ throw new IOException("Bad luck");
+ }
+
+ @Override
+ public ImageReader createReaderInstance(Object extension) {
+ return null;
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ MarkTryFinallyReproducerSpi spi = new MarkTryFinallyReproducerSpi();
+ IIORegistry.getDefaultInstance().registerServiceProvider(spi);
+
+ ImageInputStream iis1 =
+ new NotClosingImageInputStream(ImageIO.createImageInputStream(new ByteArrayInputStream(bmp)));
+ iis1.readByte();
+ iis1.mark();
+ long p1 = iis1.getStreamPosition();
+ iis1.readByte();
+ iis1.mark();
+ long p2 = iis1.getStreamPosition();
+ BufferedImage bi1 = ImageIO.read(iis1);
+ iis1.reset();
+ long pn2 = iis1.getStreamPosition();
+ iis1.reset();
+ long pn1 = iis1.getStreamPosition();
+ if (p1 != pn1 || p2!= pn2) {
+ throw new RuntimeException("Exception from call to canDecodeInput in ImageIO. " +
+ "Corrupted stack in ImageInputStream");
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/MBeanServer/ExceptionFactory.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2008, 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.util.ArrayList;
+import javax.management.AttributeNotFoundException;
+import javax.management.BadAttributeValueExpException;
+import javax.management.BadBinaryOpValueExpException;
+import javax.management.BadStringOperationException;
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.IntrospectionException;
+import javax.management.InvalidApplicationException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.JMException;
+import javax.management.JMRuntimeException;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.OperationsException;
+import javax.management.ReflectionException;
+import javax.management.RuntimeErrorException;
+import javax.management.RuntimeMBeanException;
+import javax.management.RuntimeOperationsException;
+import javax.management.ServiceNotFoundException;
+import javax.management.StringValueExp;
+import javax.management.modelmbean.InvalidTargetObjectTypeException;
+import javax.management.modelmbean.XMLParseException;
+import javax.management.monitor.MonitorSettingException;
+import javax.management.openmbean.InvalidKeyException;
+import javax.management.openmbean.InvalidOpenTypeException;
+import javax.management.openmbean.KeyAlreadyExistsException;
+import javax.management.openmbean.OpenDataException;
+import javax.management.relation.InvalidRelationIdException;
+import javax.management.relation.InvalidRelationServiceException;
+import javax.management.relation.InvalidRelationTypeException;
+import javax.management.relation.InvalidRoleInfoException;
+import javax.management.relation.InvalidRoleValueException;
+import javax.management.relation.RelationException;
+import javax.management.relation.RelationNotFoundException;
+import javax.management.relation.RelationServiceNotRegisteredException;
+import javax.management.relation.RelationTypeNotFoundException;
+import javax.management.relation.RoleInfoNotFoundException;
+import javax.management.relation.RoleNotFoundException;
+import javax.management.remote.JMXProviderException;
+import javax.management.remote.JMXServerErrorException;
+
+/**
+ * |----- Original Description Coming From Tonga Original Source Code -------|
+ * | |
+ * | That class creates an ArrayList and fill it with an instance of each of |
+ * | the Exception class of the JMX API. |
+ * | It's dedicated to use by ExceptionTest. |
+ * |-------------------------------------------------------------------------|
+ */
+public class ExceptionFactory {
+
+ public static final ArrayList<Exception> exceptions =
+ new ArrayList<Exception>();
+
+ static {
+ String mes = "SQE";
+ exceptions.add(new AttributeNotFoundException());
+ exceptions.add(new BadAttributeValueExpException(mes));
+ exceptions.add(new BadBinaryOpValueExpException(new StringValueExp(mes)));
+ exceptions.add(new BadStringOperationException(mes));
+ exceptions.add(new InstanceAlreadyExistsException());
+ exceptions.add(new InstanceNotFoundException());
+ exceptions.add(new IntrospectionException());
+ exceptions.add(new InvalidApplicationException(mes));
+ exceptions.add(new InvalidAttributeValueException());
+ exceptions.add(new JMException());
+ exceptions.add(new JMRuntimeException());
+ exceptions.add(new ListenerNotFoundException());
+ exceptions.add(new MalformedObjectNameException());
+ exceptions.add(new MBeanException(new Exception(mes), mes));
+ exceptions.add(new MBeanRegistrationException(new Exception(mes), mes));
+ exceptions.add(new NotCompliantMBeanException());
+ exceptions.add(new OperationsException());
+ exceptions.add(new ReflectionException(new Exception(mes), mes));
+ exceptions.add(new RuntimeErrorException(new Error(mes), mes));
+ exceptions.add(new RuntimeMBeanException(new RuntimeException(mes), mes));
+ exceptions.add(new RuntimeOperationsException(new RuntimeException(mes), mes));
+ exceptions.add(new ServiceNotFoundException());
+ exceptions.add(new InvalidTargetObjectTypeException());
+ exceptions.add(new XMLParseException());
+ exceptions.add(new MonitorSettingException());
+ exceptions.add(new InvalidKeyException());
+ exceptions.add(new InvalidOpenTypeException());
+ exceptions.add(new KeyAlreadyExistsException());
+ exceptions.add(new OpenDataException());
+ exceptions.add(new InvalidRelationIdException());
+ exceptions.add(new InvalidRelationServiceException());
+ exceptions.add(new InvalidRelationTypeException());
+ exceptions.add(new InvalidRoleInfoException());
+ exceptions.add(new InvalidRoleValueException());
+ exceptions.add(new RelationException());
+ exceptions.add(new RelationNotFoundException());
+ exceptions.add(new RelationServiceNotRegisteredException());
+ exceptions.add(new RelationTypeNotFoundException());
+ exceptions.add(new RoleInfoNotFoundException());
+ exceptions.add(new RoleNotFoundException());
+ exceptions.add(new JMXProviderException());
+ exceptions.add(new JMXServerErrorException(mes, new Error(mes)));
+ ExceptionTest.Utils.debug(ExceptionTest.Utils.DEBUG_STANDARD,
+ "DataFactory::updateMap: Initialized" +
+ " an ArrayList with the " +
+ exceptions.size() + " exceptions of the JMX API");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/MBeanServer/ExceptionTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks that exceptions are correctly wired (compared to reference).
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD ExceptionTest
+ */
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.lang.reflect.Method;
+
+import java.lang.management.ManagementFactory;
+import javax.management.ObjectName;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+
+public class ExceptionTest {
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ ExceptionTest test = new ExceptionTest();
+ test.run(map);
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("ExceptionTest::run: Start");
+ int errorCount = 0;
+
+ JMXConnectorServer cs = null;
+ JMXConnector cc = null;
+
+ try {
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // ----
+ ObjectName objName =
+ new ObjectName(ExceptionThrower.EXCEPTION_THROWER_NAME);
+ System.out.println("ExceptionTest::run: Create and register MBean " + objName);
+ mbsc.createMBean("ExceptionThrower", objName);
+ System.out.println("---- OK\n");
+
+ // ----
+ System.out.println("ExceptionTest::run: Ask for exception(s)");
+ Object[] throwExceptionParam = new Object[1];
+ String[] throwExceptionSig = new String[]{"int"};
+
+ for (int i = 0; i < ExceptionFactory.exceptions.size(); i++) {
+ throwExceptionParam[0] = new Integer(i);
+
+ Exception ex =
+ (Exception)mbsc.invoke(objName,
+ "throwException", throwExceptionParam, throwExceptionSig);
+
+ if ( ! matches(ex, ExceptionFactory.exceptions.get(i)) ) {
+ errorCount++;
+ System.out.println("ExceptionTest::run: (ERROR) Received \n["
+ + ex + "]\nin place of\n["
+ + ExceptionFactory.exceptions.get(i) + "]");
+ } else {
+ System.out.println("OK [" + ex + "]");
+ }
+ }
+
+ System.out.println("---- DONE\n");
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true);
+ throw new RuntimeException();
+ } finally {
+ try {
+ // Close JMX Connector Client
+ cc.close();
+ // Stop connertor server
+ cs.stop();
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true);
+ throw new RuntimeException(
+ "Unable to either close connector client or stop connector server");
+ }
+ }
+
+ if (errorCount == 0) {
+ System.out.println("ExceptionTest::run: Done without any error");
+ } else {
+ System.out.println("ExceptionTest::run: Done with " + errorCount
+ + " error(s)");
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+
+ System.out.println("ExceptionTest::run: Done");
+ }
+
+ // Check both Exception are identical.
+ // That means:
+ // - none is null.
+ // - they are of the same Class.
+ // - if their respective messages aren't null they're equal.
+ // - if the message of one is null the message of the other is null too.
+ private boolean matches(Exception ex, Exception refex) {
+ if ( ex == null || refex == null ) {
+ System.out.println("(ERROR) Called with one or more null parameter; check "
+ + ex + " against " + refex);
+ return false;
+ }
+
+ String exClass = ex.getClass().getName();
+ String refexClass = refex.getClass().getName();
+
+ if ( ! exClass.equals(refexClass) ) {
+ System.out.println("(ERROR) Class names don't match; check ["
+ + exClass + "] against [" + refexClass + "]");
+ return false;
+ }
+
+ String exMes = ex.getMessage();
+ String refexMes = refex.getMessage();
+
+ if ( exMes != null && refexMes != null ) {
+ if ( ! exMes.equals(refexMes) ) {
+ System.out.println("(ERROR) Non null messages don't match; check ["
+ + exMes + "] against [" + refexMes + "]");
+ return false;
+ }
+ } else if ( (exMes == null && refexMes != null)
+ || (exMes != null && refexMes == null) ) {
+ System.out.println("(ERROR) Messages don't match; check [" + exMes
+ + "] against [" + refexMes + "]");
+ }
+
+ return true;
+ }
+
+ // Utility inner class coming from JMX Tonga test suite.
+ // Also used by ExceptionFactory.
+ static class Utils {
+
+ // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property
+ static final String DEBUG_HEADER = "[debug] ";
+
+ // DEBUG levels
+ static int selectedDebugLevel = 0;
+ static final int DEBUG_STANDARD = 1;
+ static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests
+ static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE;
+
+ static void parseDebugProperties() {
+ int level = 0;
+ Properties p = System.getProperties();
+
+ // get selected levels
+ if (p.getProperty("DEBUG_STANDARD") != null) {
+ level |= DEBUG_STANDARD;
+ }
+
+ if (p.getProperty("DEBUG_VERBOSE") != null) {
+ level |= DEBUG_VERBOSE;
+ }
+
+ if (p.getProperty("DEBUG_ALL") != null) {
+ level |= DEBUG_ALL;
+ }
+
+ selectedDebugLevel = level;
+ }
+
+ /**
+ * Reproduces the original parsing and collection of test parameters
+ * from the DTonga JMX test suite.
+ *
+ * Collects passed args and returns them in a map(argname, value) structure,
+ * which will be then propagated as necessary to various called methods.
+ */
+ static Map<String, Object> parseParameters(String args[])
+ throws Exception {
+ debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start");
+ HashMap<String, Object> map = new HashMap<>();
+
+ for ( int i = 0; i < args.length; i++ ) {
+ if ( args[i].trim().startsWith("-") ) {
+ if ((i+1) < args.length && !args[i+1].startsWith("-") ) {
+ debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with value " +
+ args[i+1]) ;
+ map.put(args[i].trim(), args[i+1].trim()) ;
+ } else if ((i+1) < args.length && args[i+1].startsWith("-") ||
+ (i+1) == args.length ) {
+ debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with null value") ;
+ map.put(args[i].trim(), null) ;
+ } else {
+ System.out.println(
+ "TestRoot::parseParameters: (WARNING) not added in map = " +
+ args[i]) ;
+ }
+ }
+ }
+
+ debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ;
+ return map ;
+ }
+
+ /**
+ * This method is to be used in all tests to print anything
+ * that is temporary.
+ * Printing is done only when debug is activated by the property DEBUG.
+ * Printing depends also on the DEBUG_LEVEL property.
+ * Here it encapsulates a System.out.println.
+ */
+ static void debug(int level, String line) {
+ if ((selectedDebugLevel & level) != 0) {
+ System.out.println(DEBUG_HEADER + line);
+ }
+ }
+
+ /**
+ * Do print stack trace when withStack is true.
+ * Does try to call getTargetException() and getTargetError() then
+ * print embedded stacks in the case of an Exception wrapping
+ * another Exception or an Error. Recurse until no more wrapping
+ * is found.
+ */
+ static void printThrowable(Throwable theThro, boolean withStack) {
+ try {
+ if (withStack) {
+ theThro.printStackTrace(System.out);
+ }
+ if (theThro instanceof Exception) {
+ Exception t = (Exception) theThro;
+ Method target = null;
+ String blank = " ";
+ try {
+ target = t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not
+ }
+ System.out.println(blank + t.getClass() + "==>" + t.getMessage());
+ while (target != null) {
+ try {
+ t = (Exception) target.invoke(t,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ t = null;
+ }
+ try {
+ if (t != null) {
+ blank = blank + " ";
+ System.out.println(blank + t.getClass() + "==>" +
+ t.getMessage());
+ try {
+ target =
+ t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not }
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+
+ // We may have exceptions wrapping an Error then it is
+ // getTargetError that is likely to be called
+ try {
+ target = ((Exception) theThro).getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ Throwable err = theThro;
+ while (target != null) {
+ try {
+ err = (Error) target.invoke(err,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ err = null;
+ }
+ try {
+ if (err != null) {
+ blank = blank + " ";
+ System.out.println(blank + err.getClass() + "==>" +
+ err.getMessage());
+ if (withStack) {
+ err.printStackTrace(System.out);
+ }
+ try {
+ target = err.getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+ } else {
+ System.out.println("Throwable is : " + theThro);
+ }
+ } catch (Throwable x) {
+ System.out.println("Exception : raised in printException : " + x);
+ }
+ }
+ }
+
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/MBeanServer/ExceptionThrower.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+/**
+ * This class defines a simple standard MBean.
+ */
+public class ExceptionThrower implements ExceptionThrowerMBean {
+
+ public static final String EXCEPTION_THROWER_NAME
+ = "sqe:type=ExceptionThrower";
+
+ public Exception throwException(int exceptionIndex) {
+ return ExceptionFactory.exceptions.get(exceptionIndex);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/MBeanServer/ExceptionThrowerMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2008, 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.
+ */
+
+/**
+ * This interface defines a simple standard MBean.
+ */
+public interface ExceptionThrowerMBean {
+ public Exception throwException(int exceptionIndex);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/Basic.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2005, 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.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.Notification;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationEmitter;
+import javax.management.NotificationFilter;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+
+/**
+ * Class Basic
+ * Basic Description
+ */
+public class Basic implements BasicMXBean, NotificationEmitter,
+ MBeanRegistration {
+
+ public static final String EXCEPTION_MESSAGE = "from Basic";
+ public static final String NOTIFICATION_MESSAGE = "from Basic";
+ /** Attribute : IntAtt */
+ private int intAtt = 0;
+ /** Attribute : IntegerAtt */
+ private Integer integerAtt = 0;
+ /** Attribute : BoolAtt */
+ private boolean boolAtt = false;
+ /** Attribute : BooleanAtt */
+ private Boolean booleanAtt = false;
+ /** Attribute : StringAtt */
+ private String stringAtt = null;
+ /** Attribute : DateAtt */
+ private Date dateAtt = null;
+ /** Attribute : ObjectNameAtt */
+ private ObjectName objectNameAtt = null;
+ /** Attribute : NotifDescriptorAsMapAtt */
+ private Map<String, String> notifDescriptorAsMapAtt = null;
+ /** Attribute : NotifDescriptorAtt */
+ private Descriptor notifDescriptorAtt = null;
+ /** Attribute : SqeParameter */
+ private SqeParameter sqeParameterAtt = null;
+
+ /* Creates a new instance of Basic */
+ @SqeDescriptorKey("CONSTRUCTOR Basic")
+ public Basic() {
+ }
+
+ /* Creates a new instance of Basic */
+ @SqeDescriptorKey("CONSTRUCTOR Basic")
+ public Basic(
+ @SqeDescriptorKey("CONSTRUCTOR PARAMETER SqeParameter") SqeParameter param) {
+ }
+
+ /**
+ * Get int attribute
+ */
+ public int getIntAtt() {
+ return intAtt;
+ }
+
+ /**
+ * Set int attribute
+ */
+ public void setIntAtt(int value) {
+ intAtt = value;
+ }
+
+ /**
+ * Get Integer attribute
+ */
+ public Integer getIntegerAtt() {
+ return integerAtt;
+ }
+
+ /**
+ * Set Integer attribute
+ */
+ public void setIntegerAtt(Integer value) {
+ integerAtt = value;
+ }
+
+ /**
+ * Get boolean attribute
+ */
+ public boolean getBoolAtt() {
+ return boolAtt;
+ }
+
+ /**
+ * Set boolean attribute
+ */
+ public void setBoolAtt(boolean value) {
+ boolAtt = value;
+ }
+
+ /**
+ * Get Boolean attribute
+ */
+ public Boolean getBooleanAtt() {
+ return booleanAtt;
+ }
+
+ /**
+ * Set Boolean attribute
+ */
+ public void setBooleanAtt(Boolean value) {
+ booleanAtt = value;
+ }
+
+ /**
+ * Get String attribute
+ */
+ public String getStringAtt() {
+ return stringAtt;
+ }
+
+ /**
+ * Set String attribute
+ */
+ public void setStringAtt(String value) {
+ stringAtt = value;
+ }
+
+ /**
+ * Get Date attribute
+ */
+ public Date getDateAtt() {
+ return dateAtt;
+ }
+
+ /**
+ * Set Date attribute
+ */
+ public void setDateAtt(Date value) {
+ dateAtt = value;
+ }
+
+ /**
+ * Get ObjectName attribute
+ */
+ public ObjectName getObjectNameAtt() {
+ return objectNameAtt;
+ }
+
+ /**
+ * Set ObjectName attribute
+ */
+ public void setObjectNameAtt(ObjectName value) {
+ objectNameAtt = value;
+ }
+
+ /**
+ * Get SqeParameter attribute
+ */
+ public SqeParameter getSqeParameterAtt() throws Exception {
+ if (sqeParameterAtt == null) {
+ sqeParameterAtt = new SqeParameter();
+ sqeParameterAtt.setGlop("INITIALIZED");
+ }
+
+ return sqeParameterAtt;
+ }
+
+ /**
+ * Set SqeParameter attribute
+ */
+ public void setSqeParameterAtt(SqeParameter value) {
+ sqeParameterAtt = value;
+ }
+
+ /**
+ * Get the Descriptor used to build the NotificationInfo
+ * of emitted notifications.
+ */
+ public Map<String, String> getNotifDescriptorAsMapAtt() {
+ if (notifDescriptorAsMapAtt == null) {
+ initNotifDescriptorAtt();
+ }
+
+ return notifDescriptorAsMapAtt;
+ }
+
+ /**
+ * Set the Descriptor used to build the NotificationInfo
+ * of emitted notifications.
+ * <br>A Map<String, Object> would better fit Descriptor needs but then
+ * it is not convertible according the MXBean specification so the MBean
+ * registration fails.
+ * As we plan to test our custom Descriptor finds its way into
+ * the metadata of emitted notifications, String is good enough.
+ */
+ public void setNotifDescriptorAsMapAtt(Map<String, String> value) {
+ notifDescriptorAsMapAtt = new HashMap<String, String>(value);
+ notifDescriptorAtt = new ImmutableDescriptor(value);
+ }
+
+ /**
+ * Do nothing
+ */
+ public void doNothing() {
+ // I said NOTHING !
+ }
+
+ /**
+ * Do take SqeParameter as a parameter
+ */
+ public void doWeird(SqeParameter param) {
+ }
+
+ /**
+ * Throw an Exception
+ */
+ public void throwException() throws Exception {
+ throw new Exception(EXCEPTION_MESSAGE);
+ }
+
+ /**
+ * Throw an Error
+ */
+ public void throwError() {
+ throw new InternalError(EXCEPTION_MESSAGE);
+ }
+
+ /**
+ * Reset all attributes
+ */
+ public void reset() {
+ intAtt = 0;
+ integerAtt = 0;
+ boolAtt = false;
+ booleanAtt = Boolean.FALSE;
+ stringAtt = null;
+ dateAtt = null;
+ objectNameAtt = null;
+ }
+
+ /**
+ * Returns the weather for the coming days
+ * @param verbose <code>boolean</code> verbosity
+ * @throws java.lang.Exception <code>storm</code>
+ * @return <code>ObjectName</code>
+ */
+ public Weather getWeather(boolean verbose)
+ throws java.lang.Exception {
+ return Weather.SUNNY;
+ }
+
+ // Starting here are the 4 methods of MBeanRegistration interface.
+ // We use that to grab the ObjectName the MBean is registered with.
+ //
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ // Grab a reference on the MBeanServer we're registered in.
+ mbs = server;
+ // Compute the name we're registered with.
+ if (name != null) {
+ mbeanName = name;
+ return name;
+ } else {
+ mbeanName =
+ new ObjectName("sqe:type=" + Basic.class.getName());
+ return mbeanName;
+ }
+ }
+
+ public void postRegister(Boolean registrationDone) {
+ // Do nothing
+ }
+
+ public void preDeregister() throws Exception {
+ // Do nothing
+ }
+
+ public void postDeregister() {
+ // Do nothing
+ }
+
+ /**
+ * Send one Notification of the provided notifType type.
+ */
+ public void sendNotification(String notifType) {
+ Notification notification = null;
+
+ if (notifType.equals(NOTIF_TYPE_0)) {
+ notification = new Notification(NOTIF_TYPE_0,
+ mbeanName,
+ seqNumber,
+ NOTIFICATION_MESSAGE);
+ } else if (notifType.equals(NOTIF_TYPE_1)) {
+ notification = new SqeNotification(NOTIF_TYPE_1,
+ mbeanName,
+ seqNumber,
+ NOTIFICATION_MESSAGE);
+ }
+
+ seqNumber++;
+ broadcaster.sendNotification(notification);
+ }
+
+ /**
+ * That method starts a set of threads, each thread sends a given number of
+ * notifications.
+ * The number of threads can be set via the attribute numOfNotificationSenders.
+ * The number of notification sent by each thread can be set via
+ * the attribute numOfNotificationSenderLoops.
+ * Depending on the parameter customNotification we send either custom
+ * notification(s) or MBeanServer registration and unregistration notification(s).
+ * When customNotification=true the total number of notification(s) sent is
+ * (numOfNotificationSenders * numOfNotificationSenderLoops). They are
+ * sequentially of type NOTIF_TYPE_0 then NOTIF_TYPE_1 and so on.
+ *
+ * When customNotification=false the total number of notification(s) sent is
+ * (numOfNotificationSenders * numOfNotificationSenderLoops) registration
+ * notification(s)
+ * +
+ * (numOfNotificationSenders * numOfNotificationSenderLoops) unregistration
+ * notification(s)
+ *
+ * @throws java.lang.Exception
+ */
+ public void sendNotificationWave(boolean customNotification) throws
+ Exception {
+ // Build the set of notification sender.
+ Collection<Callable<Integer>> tasks =
+ new HashSet<Callable<Integer>>(numOfNotificationSenders);
+
+ for (int i = 1; i <= numOfNotificationSenders; i++) {
+ tasks.add(new NotifSender(numOfNotificationSenderLoops,
+ customNotification, i));
+ }
+
+ // Start all notification sender in parallel.
+ ExecutorService execServ = null;
+ try {
+ execServ = Executors.newFixedThreadPool(numOfNotificationSenders);
+ List<Future<Integer>> taskHandlers = execServ.invokeAll(tasks);
+ checkNotifSenderThreadStatus(taskHandlers);
+ } finally {
+ if (!execServ.isShutdown()) {
+ execServ.shutdown();
+ }
+ }
+ }
+
+ public void setNumOfNotificationSenders(int value) {
+ numOfNotificationSenders = value;
+ }
+
+ public void setNumOfNotificationSenderLoops(int value) {
+ numOfNotificationSenderLoops = value;
+ }
+
+ /**
+ * MBean Notification support
+ * You shouldn't update these methods
+ */
+ // <editor-fold defaultstate="collapsed" desc=" Generated Code ">
+ public void addNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws IllegalArgumentException {
+ broadcaster.addNotificationListener(listener, filter, handback);
+ }
+
+ public MBeanNotificationInfo[] getNotificationInfo() {
+ if (notifDescriptorAtt == null) {
+ initNotifDescriptorAtt();
+ }
+
+ return new MBeanNotificationInfo[]{
+ new MBeanNotificationInfo(new String[]{
+ NOTIF_TYPE_0
+ },
+ javax.management.Notification.class.getName(),
+ "Standard JMX Notification",
+ notifDescriptorAtt),
+ new MBeanNotificationInfo(new String[]{
+ NOTIF_TYPE_1
+ },
+ SqeNotification.class.getName(),
+ "SQE Notification",
+ notifDescriptorAtt)
+ };
+ }
+
+ public void removeNotificationListener(NotificationListener listener)
+ throws ListenerNotFoundException {
+ broadcaster.removeNotificationListener(listener);
+ }
+
+ public void removeNotificationListener(NotificationListener listener,
+ NotificationFilter filter,
+ Object handback)
+ throws ListenerNotFoundException {
+ broadcaster.removeNotificationListener(listener, filter, handback);
+ }
+ // </editor-fold>
+ private synchronized long getNextSeqNumber() {
+ return seqNumber++;
+ }
+
+ private void initNotifDescriptorAtt() {
+ String key = "CRABE";
+ String value = "TAMBOUR";
+ notifDescriptorAtt =
+ new ImmutableDescriptor(new String[]{key + "=" + value});
+ notifDescriptorAsMapAtt =
+ new HashMap<String, String>();
+ notifDescriptorAsMapAtt.put(key, value);
+ }
+
+ private void checkNotifSenderThreadStatus(
+ List<Future<Integer>> taskHandlers)
+ throws Exception {
+ String msgTag = "Basic::checkNotifSenderThreadStatus: ";
+ // Grab back status of each notification sender.
+ for (Future<Integer> f : taskHandlers) {
+ if (f.isCancelled()) {
+ String message = msgTag +
+ "---- ERROR : One thread has been cancelled";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ } else {
+ Integer effectiveNumOfLoops = f.get();
+
+ if (effectiveNumOfLoops != numOfNotificationSenderLoops) {
+ String message = msgTag + "---- ERROR : One thread did " +
+ effectiveNumOfLoops + " loops in place of " +
+ numOfNotificationSenderLoops;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+ }
+ }
+ //
+ private int numOfNotificationSenderLoops = 2;
+ private int numOfNotificationSenders = 13;
+
+ private class NotifSender implements Callable<Integer> {
+
+ private int cycles;
+ private boolean customNotification;
+ private int senderID;
+
+ public NotifSender(int cycles, boolean customNotification, int id) {
+ this.cycles = cycles;
+ this.customNotification = customNotification;
+ this.senderID = id;
+ }
+
+ public Integer call() throws Exception {
+ int callsDone = 0;
+
+ try {
+ for (int i = 1; i <= cycles; i++) {
+ if (customNotification) {
+ if (i % 2 == 0) {
+ sendNotification(NOTIF_TYPE_0);
+ } else {
+ sendNotification(NOTIF_TYPE_1);
+ }
+ } else {
+ ObjectName mbeanName = new ObjectName("SQE:type=" +
+ mbeanClassName + ",senderID=" + senderID);
+ mbs.createMBean(mbeanClassName, mbeanName);
+ mbs.unregisterMBean(mbeanName);
+ }
+ callsDone++;
+ }
+ } catch (Exception e) {
+ System.out.println("NotifSender::call: (ERROR) Thread [" + senderID +
+ "] failed after " + callsDone + " cycles");
+ throw e;
+ }
+
+ return Integer.valueOf(callsDone);
+ }
+ }
+
+ //
+ private long seqNumber;
+ private final NotificationBroadcasterSupport broadcaster =
+ new NotificationBroadcasterSupport();
+ private ObjectName mbeanName;
+ private MBeanServer mbs;
+ private String mbeanClassName = "Simple";
+
+ /**
+ * Notification types definitions. To use when creating JMX Notifications.
+ */
+ public static final String NOTIF_TYPE_0 =
+ "sqe.notification.a.type";
+ public static final String NOTIF_TYPE_1 =
+ "sqe.notification.b.type";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/BasicMXBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2005, 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.util.Date;
+import java.util.Map;
+
+import javax.management.ObjectName;
+
+/**
+ * Interface BasicMBean
+ * Basic Description
+ */
+@SqeDescriptorKey("INTERFACE BasicMXBean")
+public interface BasicMXBean
+{
+ /**
+ * Get int attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE intAtt")
+ public int getIntAtt();
+
+ /**
+ * Set int attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE intAtt")
+ public void setIntAtt(int value);
+
+ /**
+ * Get Integer attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE integerAtt")
+ public Integer getIntegerAtt();
+
+ /**
+ * Set Integer attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE integerAtt")
+ public void setIntegerAtt(Integer value);
+
+ /**
+ * Get boolean attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE boolAtt")
+ public boolean getBoolAtt();
+
+ /**
+ * Set boolean attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE boolAtt")
+ public void setBoolAtt(boolean value);
+
+ /**
+ * Get Boolean attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE booleanAtt")
+ public Boolean getBooleanAtt();
+
+ /**
+ * Set Boolean attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE booleanAtt")
+ public void setBooleanAtt(Boolean value);
+
+ /**
+ * Get String attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE stringAtt")
+ public String getStringAtt();
+
+ /**
+ * Set String attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE stringAtt")
+ public void setStringAtt(String value);
+
+ /**
+ * Get Date attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE dateAtt")
+ public Date getDateAtt();
+
+ /**
+ * Set Date attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE dateAtt")
+ public void setDateAtt(Date value);
+
+ /**
+ * Get ObjectName attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE objectNameAtt")
+ public ObjectName getObjectNameAtt();
+
+ /**
+ * Set ObjectName attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE objectNameAtt")
+ public void setObjectNameAtt(ObjectName value);
+
+ /**
+ * Get SqeParameter attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE sqeParameterAtt")
+ public SqeParameter getSqeParameterAtt() throws Exception;
+
+ /**
+ * Set SqeParameter attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE sqeParameterAtt")
+ public void setSqeParameterAtt(SqeParameter value);
+
+ /**
+ * Set NumOfNotificationSenders attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE NumOfNotificationSenders")
+ public void setNumOfNotificationSenders(int value);
+
+ /**
+ * Set NumOfNotificationSenderLoops attribute
+ */
+ @SqeDescriptorKey("ATTRIBUTE NumOfNotificationSenderLoops")
+ public void setNumOfNotificationSenderLoops(int value);
+
+ /**
+ * do nothing
+ *
+ */
+ @SqeDescriptorKey("OPERATION doNothing")
+ public void doNothing();
+
+ /**
+ * Do take SqeParameter as a parameter
+ */
+ @SqeDescriptorKey("OPERATION doWeird")
+ public void doWeird(@SqeDescriptorKey("METHOD PARAMETER")SqeParameter param);
+
+ /**
+ * throw an Exception
+ *
+ */
+ @SqeDescriptorKey("OPERATION throwException")
+ public void throwException() throws Exception;
+
+ /**
+ * throw an Error
+ *
+ */
+ @SqeDescriptorKey("OPERATION throwError")
+ public void throwError();
+
+ /**
+ * reset all attributes
+ *
+ */
+ @SqeDescriptorKey("OPERATION reset")
+ public void reset();
+
+ /**
+ * returns the weather for the coming days
+ *
+ * @param verbose <code>boolean</code> verbosity
+ * @return <code>ObjectName</code>
+ */
+ @SqeDescriptorKey("OPERATION getWeather")
+ public Weather getWeather(@SqeDescriptorKey("METHOD PARAMETER")boolean verbose)
+ throws java.lang.Exception;
+
+ public enum Weather {
+ CLOUDY, SUNNY
+ }
+
+ @SqeDescriptorKey("ATTRIBUTE notifDescriptorAsMapAtt")
+ public Map<String, String> getNotifDescriptorAsMapAtt();
+
+ @SqeDescriptorKey("ATTRIBUTE notifDescriptorAsMapAtt")
+ public void setNotifDescriptorAsMapAtt(Map<String, String> value);
+
+ @SqeDescriptorKey("OPERATION sendNotification")
+ public void sendNotification(@SqeDescriptorKey("METHOD PARAMETER")String notifType);
+
+ @SqeDescriptorKey("OPERATION sendNotificationWave")
+ public void sendNotificationWave(boolean customNotification) throws Exception;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanExceptionHandlingTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks correct exception and error events from NotificationListener
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Basic.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanExceptionHandlingTest -timeForNotificationInSeconds 3
+ */
+
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanException;
+import javax.management.MBeanServerDelegate;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.RuntimeErrorException;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+public class MXBeanExceptionHandlingTest implements NotificationListener {
+
+ private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
+
+ private long timeForNotificationInSeconds = 3L;
+ private int numOfNotifications = 2;
+ private BlockingQueue<Notification> notifList = null;
+
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanExceptionHandlingTest test = new MXBeanExceptionHandlingTest();
+ test.run(map);
+
+ }
+
+ protected void parseArgs(Map<String, Object> args) throws Exception {
+
+ String arg = null;
+
+ // Init timeForNotificationInSeconds
+ // It is the maximum time in seconds we wait for a notification.
+ arg = (String)args.get("-timeForNotificationInSeconds") ;
+ if (arg != null) {
+ timeForNotificationInSeconds = (new Long(arg)).longValue();
+ }
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanExceptionHandlingTest::run: Start") ;
+ int errorCount = 0 ;
+
+ try {
+ parseArgs(args);
+ notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);
+
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // ----
+ System.out.println("Add me as notification listener");
+ mbsc.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
+ this, null, null);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("Create and register the MBean");
+ ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
+ mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("Call method throwException on our MXBean");
+
+ try {
+ mbsc.invoke(objName, "throwException", null, null);
+ errorCount++;
+ System.out.println("(ERROR) Did not get awaited MBeanException") ;
+ } catch (MBeanException mbe) {
+ System.out.println("(OK) Got awaited MBeanException") ;
+ Throwable cause = mbe.getCause();
+
+ if ( cause instanceof java.lang.Exception ) {
+ System.out.println("(OK) Cause is of the right class") ;
+ String mess = cause.getMessage();
+
+ if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) {
+ System.out.println("(OK) Cause message is fine") ;
+ } else {
+ errorCount++;
+ System.out.println("(ERROR) Cause has message "
+ + cause.getMessage()
+ + " as we expect "
+ + Basic.EXCEPTION_MESSAGE) ;
+ }
+ } else {
+ errorCount++;
+ System.out.println("(ERROR) Cause is of class "
+ + cause.getClass().getName()
+ + " as we expect java.lang.Exception") ;
+ }
+ } catch (Exception e) {
+ errorCount++;
+ System.out.println("(ERROR) Did not get awaited MBeanException but "
+ + e) ;
+ Utils.printThrowable(e, true);
+ }
+ System.out.println("---- DONE\n") ;
+
+ // ----
+ System.out.println("Call method throwError on our MXBean");
+
+ try {
+ mbsc.invoke(objName, "throwError", null, null);
+ errorCount++;
+ System.out.println("(ERROR) Did not get awaited RuntimeErrorException") ;
+ } catch (RuntimeErrorException ree) {
+ System.out.println("(OK) Got awaited RuntimeErrorException") ;
+ Throwable cause = ree.getCause();
+
+ if ( cause instanceof java.lang.InternalError ) {
+ System.out.println("(OK) Cause is of the right class") ;
+ String mess = cause.getMessage();
+
+ if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) {
+ System.out.println("(OK) Cause message is fine") ;
+ } else {
+ errorCount++;
+ System.out.println("(ERROR) Cause has message "
+ + cause.getMessage()
+ + " as we expect "
+ + Basic.EXCEPTION_MESSAGE) ;
+ }
+ } else {
+ errorCount++;
+ System.out.println("(ERROR) Cause is of class "
+ + cause.getClass().getName()
+ + " as we expect java.lang.InternalError") ;
+ }
+ } catch (Exception e) {
+ errorCount++;
+ System.out.println("(ERROR) Did not get awaited RuntimeErrorException but "
+ + e) ;
+ Utils.printThrowable(e, true);
+ }
+ System.out.println("---- DONE\n") ;
+
+ // ----
+ System.out.println("Unregister the MBean");
+ mbsc.unregisterMBean(objName);
+ System.out.println("---- OK\n") ;
+
+ Thread.sleep(timeForNotificationInSeconds * 1000);
+ int numOfReceivedNotif = notifList.size();
+
+ if ( numOfReceivedNotif == numOfNotifications ) {
+ System.out.println("(OK) We received "
+ + numOfNotifications
+ + " Notifications") ;
+ } else {
+ errorCount++;
+ System.out.println("(ERROR) We received "
+ + numOfReceivedNotif
+ + " Notifications in place of "
+ + numOfNotifications) ;
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanExceptionHandlingTest::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanExceptionHandlingTest::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+ }
+
+ public void handleNotification(Notification notification, Object handback) {
+ System.out.println("MXBeanExceptionHandlingTest::handleNotification: Received "
+ + notification);
+ notifList.add(notification);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest1.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Test all MXBeans available by default on the platform
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest1
+ */
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.CompilationMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryManagerMXBean;
+import java.lang.management.MemoryPoolMXBean;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+
+import javax.management.JMX;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+public class MXBeanInteropTest1 {
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanInteropTest1 test = new MXBeanInteropTest1();
+ test.run(map);
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanInteropTest1::run: Start") ;
+ int errorCount = 0 ;
+
+ try {
+ // JMX MbeanServer used inside single VM as if remote.
+ // MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // Print out registered java.lang.management MXBeans found
+ // in the remote jvm.
+ printMBeans(mbsc) ;
+
+ // For each possible kind of JDK 5 defined MXBean, we retrieve its
+ // MBeanInfo and print it and we call all getters and print
+ // their output.
+ errorCount += doClassLoadingMXBeanTest(mbsc) ;
+ errorCount += doMemoryMXBeanTest(mbsc) ;
+ errorCount += doThreadMXBeanTest(mbsc) ;
+ errorCount += doRuntimeMXBeanTest(mbsc) ;
+ errorCount += doOperatingSystemMXBeanTest(mbsc) ;
+ errorCount += doCompilationMXBeanTest(mbsc) ;
+ errorCount += doGarbageCollectorMXBeanTest(mbsc) ;
+ errorCount += doMemoryManagerMXBeanTest(mbsc) ;
+ errorCount += doMemoryPoolMXBeanTest(mbsc) ;
+
+ // Terminate the JMX Client
+ cc.close();
+
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanInteropTest1::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanInteropTest1::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+ }
+
+ /**
+ * Prints all MBeans of domain java.lang.
+ * They are MBeans related to the JSR 174 that defines
+ * package java.lang.management.
+ */
+ private static void printMBeans(MBeanServerConnection mbsc) throws Exception {
+ ObjectName filterName = new ObjectName("java.lang:*");
+ Set<ObjectName> set = mbsc.queryNames(filterName, null);
+
+ if ( set.size() == 0 ) {
+ throw new RuntimeException("(ERROR) No MBean found with filter "
+ + filterName);
+ }
+
+ System.out.println("---- MBeans found in domain java.lang :");
+
+ for (Iterator<ObjectName> iter = set.iterator(); iter.hasNext(); ) {
+ System.out.println(iter.next().toString());
+ }
+
+ System.out.println("\n") ;
+ }
+
+
+ private final int doClassLoadingMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- ClassLoadingMXBean") ;
+
+ try {
+ ObjectName classLoadingName =
+ new ObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(classLoadingName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t"
+ + mbInfo);
+ ClassLoadingMXBean classLoading = null;
+
+ classLoading = JMX.newMXBeanProxy(mbsc,
+ classLoadingName,
+ ClassLoadingMXBean.class) ;
+ System.out.println("getLoadedClassCount\t\t"
+ + classLoading.getLoadedClassCount());
+ System.out.println("getTotalLoadedClassCount\t\t"
+ + classLoading.getTotalLoadedClassCount());
+ System.out.println("getUnloadedClassCount\t\t"
+ + classLoading.getUnloadedClassCount());
+ System.out.println("isVerbose\t\t"
+ + classLoading.isVerbose());
+
+ System.out.println("---- OK\n") ;
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doMemoryMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- MemoryMXBean") ;
+
+ try {
+ ObjectName memoryName =
+ new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t"
+ + mbInfo);
+ MemoryMXBean memory = null ;
+
+ memory =
+ JMX.newMXBeanProxy(mbsc,
+ memoryName,
+ MemoryMXBean.class,
+ true) ;
+ System.out.println("getMemoryHeapUsage\t\t"
+ + memory.getHeapMemoryUsage());
+ System.out.println("getNonHeapMemoryHeapUsage\t\t"
+ + memory.getNonHeapMemoryUsage());
+ System.out.println("getObjectPendingFinalizationCount\t\t"
+ + memory.getObjectPendingFinalizationCount());
+ System.out.println("isVerbose\t\t"
+ + memory.isVerbose());
+
+ System.out.println("---- OK\n") ;
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doThreadMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- ThreadMXBean") ;
+
+ try {
+ ObjectName threadName =
+ new ObjectName(ManagementFactory.THREAD_MXBEAN_NAME) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(threadName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ ThreadMXBean thread = null ;
+
+ thread =
+ JMX.newMXBeanProxy(mbsc,
+ threadName,
+ ThreadMXBean.class) ;
+ System.out.println("findMonitorDeadlockedThreads\t\t"
+ + thread.findMonitorDeadlockedThreads());
+ long[] threadIDs = thread.getAllThreadIds() ;
+ System.out.println("getAllThreadIds\t\t"
+ + threadIDs);
+
+ for ( long threadID : threadIDs ) {
+ System.out.println("getThreadInfo long\t\t"
+ + thread.getThreadInfo(threadID));
+ System.out.println("getThreadInfo long, int\t\t"
+ + thread.getThreadInfo(threadID, 2));
+ }
+
+ System.out.println("getThreadInfo long[]\t\t"
+ + thread.getThreadInfo(threadIDs));
+ System.out.println("getThreadInfo long[], int\t\t"
+ + thread.getThreadInfo(threadIDs, 2));
+ System.out.println("getDaemonThreadCount\t\t"
+ + thread.getDaemonThreadCount());
+ System.out.println("getPeakThreadCount\t\t"
+ + thread.getPeakThreadCount());
+ System.out.println("getThreadCount\t\t"
+ + thread.getThreadCount());
+ System.out.println("getTotalStartedThreadCount\t\t"
+ + thread.getTotalStartedThreadCount());
+ boolean supported = thread.isThreadContentionMonitoringSupported() ;
+ System.out.println("isThreadContentionMonitoringSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("isThreadContentionMonitoringEnabled\t\t"
+ + thread.isThreadContentionMonitoringEnabled());
+ }
+
+ supported = thread.isThreadCpuTimeSupported() ;
+ System.out.println("isThreadCpuTimeSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("isThreadCpuTimeEnabled\t\t"
+ + thread.isThreadCpuTimeEnabled());
+
+ for (long id : threadIDs) {
+ System.out.println("getThreadCpuTime(" + id + ")\t\t"
+ + thread.getThreadCpuTime(id));
+ System.out.println("getThreadUserTime(" + id + ")\t\t"
+ + thread.getThreadUserTime(id));
+ }
+ }
+
+ supported = thread.isCurrentThreadCpuTimeSupported() ;
+ System.out.println("isCurrentThreadCpuTimeSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("getCurrentThreadCpuTime\t\t"
+ + thread.getCurrentThreadCpuTime());
+ System.out.println("getCurrentThreadUserTime\t\t"
+ + thread.getCurrentThreadUserTime());
+ }
+
+ thread.resetPeakThreadCount() ;
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doRuntimeMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- RuntimeMXBean") ;
+
+ try {
+ ObjectName runtimeName =
+ new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(runtimeName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ RuntimeMXBean runtime = null;
+
+ runtime =
+ JMX.newMXBeanProxy(mbsc,
+ runtimeName,
+ RuntimeMXBean.class) ;
+ System.out.println("getClassPath\t\t"
+ + runtime.getClassPath());
+ System.out.println("getInputArguments\t\t"
+ + runtime.getInputArguments());
+ System.out.println("getLibraryPath\t\t"
+ + runtime.getLibraryPath());
+ System.out.println("getManagementSpecVersion\t\t"
+ + runtime.getManagementSpecVersion());
+ System.out.println("getName\t\t"
+ + runtime.getName());
+ System.out.println("getSpecName\t\t"
+ + runtime.getSpecName());
+ System.out.println("getSpecVendor\t\t"
+ + runtime.getSpecVendor());
+ System.out.println("getSpecVersion\t\t"
+ + runtime.getSpecVersion());
+ System.out.println("getStartTime\t\t"
+ + runtime.getStartTime());
+ System.out.println("getSystemProperties\t\t"
+ + runtime.getSystemProperties());
+ System.out.println("getUptime\t\t"
+ + runtime.getUptime());
+ System.out.println("getVmName\t\t"
+ + runtime.getVmName());
+ System.out.println("getVmVendor\t\t"
+ + runtime.getVmVendor());
+ System.out.println("getVmVersion\t\t"
+ + runtime.getVmVersion());
+ boolean supported = runtime.isBootClassPathSupported() ;
+ System.out.println("isBootClassPathSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("getBootClassPath\t\t"
+ + runtime.getBootClassPath());
+ }
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doOperatingSystemMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- OperatingSystemMXBean") ;
+
+ try {
+ ObjectName operationName =
+ new ObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(operationName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ OperatingSystemMXBean operation = null ;
+
+ operation =
+ JMX.newMXBeanProxy(mbsc,
+ operationName,
+ OperatingSystemMXBean.class) ;
+ System.out.println("getArch\t\t"
+ + operation.getArch());
+ System.out.println("getAvailableProcessors\t\t"
+ + operation.getAvailableProcessors());
+ System.out.println("getName\t\t"
+ + operation.getName());
+ System.out.println("getVersion\t\t"
+ + operation.getVersion());
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doCompilationMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- CompilationMXBean") ;
+
+ try {
+ ObjectName compilationName =
+ new ObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME);
+
+ if ( mbsc.isRegistered(compilationName) ) {
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(compilationName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ CompilationMXBean compilation = null ;
+
+ compilation =
+ JMX.newMXBeanProxy(mbsc,
+ compilationName,
+ CompilationMXBean.class) ;
+ System.out.println("getName\t\t"
+ + compilation.getName());
+ boolean supported =
+ compilation.isCompilationTimeMonitoringSupported() ;
+ System.out.println("isCompilationTimeMonitoringSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("getTotalCompilationTime\t\t"
+ + compilation.getTotalCompilationTime());
+ }
+ }
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doGarbageCollectorMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- GarbageCollectorMXBean") ;
+
+ try {
+ ObjectName filterName =
+ new ObjectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE
+ + ",*");
+ Set<ObjectName> onSet = mbsc.queryNames(filterName, null);
+
+ for (Iterator<ObjectName> iter = onSet.iterator(); iter.hasNext(); ) {
+ ObjectName garbageName = iter.next() ;
+ System.out.println("-------- " + garbageName) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(garbageName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ GarbageCollectorMXBean garbage = null ;
+
+ garbage =
+ JMX.newMXBeanProxy(mbsc,
+ garbageName,
+ GarbageCollectorMXBean.class) ;
+ System.out.println("getCollectionCount\t\t"
+ + garbage.getCollectionCount());
+ System.out.println("getCollectionTime\t\t"
+ + garbage.getCollectionTime());
+ }
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doMemoryManagerMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- MemoryManagerMXBean") ;
+
+ try {
+ ObjectName filterName =
+ new ObjectName(ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE
+ + ",*");
+ Set<ObjectName> onSet = mbsc.queryNames(filterName, null);
+
+ for (Iterator<ObjectName> iter = onSet.iterator(); iter.hasNext(); ) {
+ ObjectName memoryManagerName = iter.next() ;
+ System.out.println("-------- " + memoryManagerName) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryManagerName);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ errorCount += checkNonEmpty(mbInfo);
+ MemoryManagerMXBean memoryManager = null;
+
+ memoryManager =
+ JMX.newMXBeanProxy(mbsc,
+ memoryManagerName,
+ MemoryManagerMXBean.class) ;
+ System.out.println("getMemoryPoolNames\t\t"
+ + Arrays.deepToString(memoryManager.getMemoryPoolNames()));
+ System.out.println("getName\t\t"
+ + memoryManager.getName());
+ System.out.println("isValid\t\t"
+ + memoryManager.isValid());
+ }
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private final int doMemoryPoolMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- MemoryPoolMXBean") ;
+
+ try {
+ ObjectName filterName =
+ new ObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE
+ + ",*");
+ Set<ObjectName> onSet = mbsc.queryNames(filterName, null);
+
+ for (Iterator<ObjectName> iter = onSet.iterator(); iter.hasNext(); ) {
+ ObjectName memoryPoolName = iter.next() ;
+ System.out.println("-------- " + memoryPoolName) ;
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(memoryPoolName);
+ errorCount += checkNonEmpty(mbInfo);
+ System.out.println("getMBeanInfo\t\t" + mbInfo);
+ MemoryPoolMXBean memoryPool = null;
+
+ memoryPool =
+ JMX.newMXBeanProxy(mbsc,
+ memoryPoolName,
+ MemoryPoolMXBean.class,
+ true) ;
+ System.out.println("getCollectionUsage\t\t"
+ + memoryPool.getCollectionUsage());
+ System.out.println("getMemoryManagerNames\t\t"
+ + Arrays.deepToString(memoryPool.getMemoryManagerNames()));
+ System.out.println("getName\t\t"
+ + memoryPool.getName());
+ System.out.println("getPeakUsage\t\t"
+ + memoryPool.getPeakUsage());
+ System.out.println("getType\t\t"
+ + memoryPool.getType());
+ System.out.println("getUsage\t\t"
+ + memoryPool.getUsage());
+ System.out.println("isValid\t\t"
+ + memoryPool.isValid());
+ boolean supported = memoryPool.isUsageThresholdSupported() ;
+ System.out.println("isUsageThresholdSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("getUsageThreshold\t\t"
+ + memoryPool.getUsageThreshold());
+ System.out.println("isUsageThresholdExceeded\t\t"
+ + memoryPool.isUsageThresholdExceeded());
+ System.out.println("getUsageThresholdCount\t\t"
+ + memoryPool.getUsageThresholdCount());
+ }
+
+ supported = memoryPool.isCollectionUsageThresholdSupported() ;
+ System.out.println("isCollectionUsageThresholdSupported\t\t"
+ + supported);
+
+ if ( supported ) {
+ System.out.println("getCollectionUsageThreshold\t\t"
+ + memoryPool.getCollectionUsageThreshold());
+ System.out.println("getCollectionUsageThresholdCount\t\t"
+ + memoryPool.getCollectionUsageThresholdCount());
+ System.out.println("isCollectionUsageThresholdExceeded\t\t"
+ + memoryPool.isCollectionUsageThresholdExceeded());
+ }
+
+ memoryPool.resetPeakUsage();
+ }
+
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+
+ private int checkNonEmpty(MBeanInfo mbi) {
+ if ( mbi.toString().length() == 0 ) {
+ System.out.println("(ERROR) MBeanInfo is empty !");
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanInteropTest2.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks access to test MXBean
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Basic.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanInteropTest2
+ */
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanConstructorInfo;
+import javax.management.MBeanServer;
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+public class MXBeanInteropTest2 {
+
+ private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanInteropTest2 test = new MXBeanInteropTest2();
+ test.run(map);
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanInteropTest2::run: Start") ;
+ int errorCount = 0 ;
+
+ try {
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // Prints all MBeans whatever the domain is.
+ printMBeans(mbsc) ;
+
+ // Call test body
+ errorCount += doBasicMXBeanTest(mbsc) ;
+
+ // Terminate the JMX Client
+ cc.close();
+
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanInteropTest2::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanInteropTest2::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+ }
+
+
+ /**
+ * Prints all MBeans whatever the domain is.
+ */
+ private static void printMBeans(MBeanServerConnection mbsc) throws Exception {
+ Set<ObjectName> set = mbsc.queryNames(null, null);
+ System.out.println("---- MBeans found :");
+
+ for (Iterator<ObjectName> iter = set.iterator(); iter.hasNext(); ) {
+ System.out.println(iter.next().toString());
+ }
+
+ System.out.println("\n") ;
+ }
+
+
+ private final int doBasicMXBeanTest(MBeanServerConnection mbsc) {
+ int errorCount = 0 ;
+ System.out.println("---- doBasicMXBeanTest") ;
+
+ try {
+ ObjectName objName =
+ new ObjectName("sqe:type=BasicMXBean") ;
+ mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(objName);
+ printMBeanInfo(mbInfo);
+ System.out.println("---- OK\n") ;
+ System.out.println("getMBeanInfo\t\t"
+ + mbInfo);
+ System.out.println("---- OK\n") ;
+
+ System.out.println("Check mxbean field in the MBeanInfo");
+ String mxbeanField =
+ (String)mbInfo.getDescriptor().getFieldValue(JMX.MXBEAN_FIELD);
+
+ if ( mxbeanField == null || ! mxbeanField.equals("true")) {
+ System.out.println("---- ERROR : Improper mxbean field value "
+ + mxbeanField);
+ errorCount++;
+ }
+ System.out.println("---- OK\n") ;
+
+ System.out.println("Set attribute ObjectNameAtt");
+ Attribute att = new Attribute("ObjectNameAtt", objName);
+ mbsc.setAttribute(objName, att);
+ ObjectName value =
+ (ObjectName)mbsc.getAttribute(objName, "ObjectNameAtt");
+
+ if ( ! value.equals(objName) ) {
+ errorCount++;
+ System.out.println("---- ERROR : setAttribute failed, got "
+ + value
+ + " while expecting "
+ + objName);
+ }
+ System.out.println("---- OK\n") ;
+
+ System.out.println("Call operation doNothing");
+ mbsc.invoke(objName, "doNothing", null, null);
+ System.out.println("---- OK\n") ;
+
+ System.out.println("Call operation getWeather");
+ Object weather = mbsc.invoke(objName,
+ "getWeather",
+ new Object[]{Boolean.TRUE},
+ new String[]{"boolean"});
+ System.out.println("Weather is " + weather);
+ System.out.println("---- OK\n") ;
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++ ;
+ System.out.println("---- ERROR\n") ;
+ }
+
+ return errorCount ;
+ }
+
+ private void printMBeanInfo(MBeanInfo mbInfo) {
+ System.out.println("Description " + mbInfo.getDescription());
+
+ for (MBeanConstructorInfo ctor : mbInfo.getConstructors()) {
+ System.out.println("Constructor " + ctor.getName());
+ }
+
+ for (MBeanAttributeInfo att : mbInfo.getAttributes()) {
+ System.out.println("Attribute " + att.getName()
+ + " [" + att.getType() + "]");
+ }
+
+ for (MBeanOperationInfo oper : mbInfo.getOperations()) {
+ System.out.println("Operation " + oper.getName());
+ }
+
+ for (MBeanNotificationInfo notif : mbInfo.getNotifications()) {
+ System.out.println("Notification " + notif.getName());
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks correct collection of MXBean's class after unregistration
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @run main/othervm/timeout=300 MXBeanLoadingTest1
+ */
+
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.Map;
+import javax.management.Attribute;
+import javax.management.JMX;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MXBean;
+import javax.management.ObjectName;
+import javax.management.loading.PrivateMLet;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+public class MXBeanLoadingTest1 {
+
+ public static void main(String[] args) throws Exception {
+ MXBeanLoadingTest1 test = new MXBeanLoadingTest1();
+ test.run((Map<String, Object>)null);
+ }
+
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanLoadingTest1::run: Start") ;
+
+ try {
+ System.out.println("We ensure no reference is retained on MXBean class"
+ + " after it is unregistered. We take time to perform"
+ + " some little extra check of Descriptors, MBean*Info.");
+
+ ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader();
+
+ if (!(myClassLoader instanceof URLClassLoader)) {
+ String message = "(ERROR) Test's class loader is not " +
+ "a URLClassLoader";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader;
+ URL[] urls = myURLClassLoader.getURLs();
+ PrivateMLet mlet = new PrivateMLet(urls, null, false);
+ Class<?> shadowClass = mlet.loadClass(TestMXBean.class.getName());
+
+ if (shadowClass == TestMXBean.class) {
+ String message = "(ERROR) MLet got original TestMXBean, not shadow";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ shadowClass = null;
+
+ MBeanServer mbs = MBeanServerFactory.createMBeanServer();
+ ObjectName mletName = new ObjectName("x:type=mlet");
+ mbs.registerMBean(mlet, mletName);
+
+ ObjectName testName = new ObjectName("x:type=test");
+ mbs.createMBean(Test.class.getName(), testName, mletName);
+
+ // That test fails because the MXBean instance is accessed via
+ // a delegate OpenMBean which has
+ ClassLoader testLoader = mbs.getClassLoaderFor(testName);
+
+ if (testLoader != mlet) {
+ System.out.println("MLet " + mlet);
+ String message = "(ERROR) MXBean's class loader is not MLet: "
+ + testLoader;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ testLoader = null;
+
+
+ // Cycle get/set/get of the attribute of type Luis.
+ // We check the set is effective.
+ CompositeData cd_B = (CompositeData)mbs.getAttribute(testName, "B");
+ CompositeType compType_B = cd_B.getCompositeType();
+
+ CompositeDataSupport cds_B =
+ new CompositeDataSupport(compType_B,
+ new String[]{"something"},
+ new Object[]{Integer.valueOf(13)});
+ Attribute myAtt = new Attribute("B", cds_B);
+ mbs.setAttribute(testName, myAtt);
+
+ CompositeData cd_B2 = (CompositeData)mbs.getAttribute(testName, "B");
+
+ if ( ((Integer)cd_B2.get("something")).intValue() != 13 ) {
+ String message = "(ERROR) The setAttribute of att B did not work;"
+ + " expect Luis.something = 13 but got "
+ + cd_B2.get("something");
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ MBeanInfo info = mbs.getMBeanInfo(testName);
+ String mxbeanField =
+ (String)info.getDescriptor().getFieldValue(JMX.MXBEAN_FIELD);
+
+ if ( mxbeanField == null || ! mxbeanField.equals("true")) {
+ String message = "(ERROR) Improper mxbean field value "
+ + mxbeanField;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ // Check the 2 attributes.
+ MBeanAttributeInfo[] attrs = info.getAttributes();
+
+ if ( attrs.length == 2 ) {
+ for (MBeanAttributeInfo mbai : attrs) {
+ String originalTypeFieldValue =
+ (String)mbai.getDescriptor().getFieldValue(JMX.ORIGINAL_TYPE_FIELD);
+ OpenType<?> openTypeFieldValue =
+ (OpenType<?>)mbai.getDescriptor().getFieldValue(JMX.OPEN_TYPE_FIELD);
+
+ if ( mbai.getName().equals("A") ) {
+ if ( !mbai.isReadable() || !mbai.isWritable()
+ || mbai.isIs()
+ || !mbai.getType().equals("int") ) {
+ String message = "(ERROR) Unexpected MBeanAttributeInfo for A "
+ + mbai;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ if ( ! originalTypeFieldValue.equals("int") ) {
+ String message = "(ERROR) Unexpected originalType in Descriptor for A "
+ + originalTypeFieldValue;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ if ( ! openTypeFieldValue.equals(SimpleType.INTEGER) ) {
+ String message = "(ERROR) Unexpected openType in Descriptor for A "
+ + originalTypeFieldValue;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ } else if ( mbai.getName().equals("B") ) {
+ if ( !mbai.isReadable() || !mbai.isWritable()
+ || mbai.isIs()
+ || !mbai.getType().equals("javax.management.openmbean.CompositeData") ) {
+ String message = "(ERROR) Unexpected MBeanAttributeInfo for B "
+ + mbai;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ if ( ! originalTypeFieldValue.equals(Luis.class.getName()) ) {
+ String message = "(ERROR) Unexpected originalType in Descriptor for B "
+ + originalTypeFieldValue;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ if ( ! openTypeFieldValue.equals(compType_B) ) {
+ String message = "(ERROR) Unexpected openType in Descriptor for B "
+ + compType_B;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ } else {
+ String message = "(ERROR) Unknown attribute name";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+ } else {
+ String message = "(ERROR) Unexpected MBeanAttributeInfo array"
+ + Arrays.deepToString(attrs);
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ // Check the MXBean operation.
+ MBeanOperationInfo[] ops = info.getOperations();
+ // The impact is ACTION_INFO as for a standard MBean it is UNKNOWN,
+ // logged 6320104.
+ if (ops.length != 1 || !ops[0].getName().equals("bogus")
+ || ops[0].getSignature().length > 0
+ || !ops[0].getReturnType().equals("void")) {
+ String message = "(ERROR) Unexpected MBeanOperationInfo array "
+ + Arrays.deepToString(ops);
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ String originalTypeFieldValue =
+ (String)ops[0].getDescriptor().getFieldValue(JMX.ORIGINAL_TYPE_FIELD);
+ OpenType<?> openTypeFieldValue =
+ (OpenType<?>)ops[0].getDescriptor().getFieldValue(JMX.OPEN_TYPE_FIELD);
+
+ if ( ! originalTypeFieldValue.equals("void") ) {
+ String message = "(ERROR) Unexpected originalType in Descriptor for bogus "
+ + originalTypeFieldValue;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ if ( ! openTypeFieldValue.equals(SimpleType.VOID) ) {
+ String message = "(ERROR) Unexpected openType in Descriptor for bogus "
+ + originalTypeFieldValue;
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ // Check there is 2 constructors.
+ if (info.getConstructors().length != 2) {
+ String message = "(ERROR) Wrong number of constructors " +
+ "in introspected bean: " +
+ Arrays.asList(info.getConstructors());
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ // Check MXBean class name.
+ if (!info.getClassName().endsWith("Test")) {
+ String message = "(ERROR) Wrong info class name: " +
+ info.getClassName();
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+
+ mbs.unregisterMBean(testName);
+ mbs.unregisterMBean(mletName);
+
+ WeakReference<PrivateMLet> mletRef =
+ new WeakReference<PrivateMLet>(mlet);
+ mlet = null;
+
+ System.out.println("MXBean registered and unregistered, waiting for " +
+ "garbage collector to collect class loader");
+
+ for (int i = 0; i < 10000 && mletRef.get() != null; i++) {
+ System.gc();
+ Thread.sleep(1);
+ }
+
+ if (mletRef.get() == null)
+ System.out.println("(OK) class loader was GC'd");
+ else {
+ String message = "(ERROR) Class loader was not GC'd";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ System.out.println("MXBeanLoadingTest1::run: Done without any error") ;
+ }
+
+
+ // I agree the use of the MXBean annotation and the MXBean suffix for the
+ // interface name are redundant but however harmless.
+ //
+ @MXBean(true)
+ public static interface TestMXBean {
+ public void bogus();
+ public int getA();
+ public void setA(int a);
+ public Luis getB();
+ public void setB(Luis mi);
+ }
+
+
+ public static class Test implements TestMXBean {
+ private Luis luis = new Luis() ;
+ public Test() {}
+ public Test(int x) {}
+
+ public void bogus() {}
+ public int getA() {return 0;}
+ public void setA(int a) {}
+ public Luis getB() {return this.luis;}
+ public void setB(Luis luis) {this.luis = luis;}
+ }
+
+
+ public static class Luis {
+ private int something = 0;
+ public Luis() {}
+ public int getSomething() {return something;}
+ public void setSomething(int v) {something = v;}
+ public void doNothing() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks MXBean proper registration both as its implementation class and interface
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Basic.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.Attribute;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+import javax.management.MBeanServer;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+public class MXBeanNotifTest implements NotificationListener {
+
+ private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
+ private static String BASIC_MXBEAN_INTERFACE_NAME = "BasicMXBean";
+
+ private long timeForNotificationInSeconds = 3L;
+ private int numOfNotifications = 1;
+ private BlockingQueue<Notification> notifList = null;
+ private int numOfNotifDescriptorElements = 13;
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanNotifTest test = new MXBeanNotifTest();
+ test.run(map);
+
+ }
+
+ protected void parseArgs(Map<String, Object> args) throws Exception {
+
+ String arg = null;
+
+ // Init numOfNotifications
+ // It is the number of notifications we should trigger and check.
+ arg = (String)args.get("-numOfNotifications") ;
+ if (arg != null) {
+ numOfNotifications = (new Integer(arg)).intValue();
+ }
+
+ // Init timeForNotificationInSeconds
+ // It is the maximum time in seconds we wait for each notification.
+ arg = (String)args.get("-timeForEachNotificationInSeconds") ;
+ if (arg != null) {
+ timeForNotificationInSeconds = (new Long(arg)).longValue();
+ }
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanNotifTest::run: Start") ;
+ int errorCount = 0 ;
+
+ try {
+ parseArgs(args);
+ notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);
+
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Create and register the MBean");
+ ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
+ mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Add me as notification listener");
+ mbsc.addNotificationListener(objName, this, null, null);
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Retrieve the Descriptor"
+ + " that should be in MBeanNotificationInfo");
+ TabularData tabData =
+ (TabularData)mbsc.getAttribute(objName, "NotifDescriptorAsMapAtt");
+ Map<String, String> descrMap = new HashMap<>();
+
+ for (Iterator<?> it = tabData.values().iterator(); it.hasNext(); ) {
+ CompositeData compData = (CompositeData)it.next();
+ descrMap.put((String)compData.get("key"),
+ (String)compData.get("value"));
+ }
+
+ Descriptor refNotifDescriptor = new ImmutableDescriptor(descrMap);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ // Because the MBean holding the targeted attribute is MXBean, we
+ // should use for the setAttribute a converted form for the
+ // attribute value as described by the MXBean mapping rules.
+ // This explains all that lovely stuff for creating a
+ // TabularDataSupport.
+ //
+ // WARNING : the MBeanInfo of the MXBean used on opposite side
+ // is computed when the MBean is registered.
+ // It means the Descriptor considered for the MBeanNotificationInfo
+ // is not the one we set in the lines below, it is too late.
+ // However, we check that set is harmless when we check
+ // the MBeanNotificationInfo.
+ //
+ System.out.println("MXBeanNotifTest::run: Set a Map<String, String>"
+ + " attribute");
+ String typeName =
+ "java.util.Map<java.lang.String,java.lang.String>";
+ String[] keyValue = new String[] {"key", "value"};
+ OpenType<?>[] openTypes =
+ new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING};
+ CompositeType rowType = new CompositeType(typeName, typeName,
+ keyValue, keyValue, openTypes);
+ TabularType tabType = new TabularType(typeName, typeName,
+ rowType, new String[]{"key"});
+ TabularDataSupport convertedDescrMap =
+ new TabularDataSupport(tabType);
+
+ for (int i = 0; i < numOfNotifDescriptorElements; i++) {
+ Object[] descrValue = {"field" + i, "value" + i};
+ CompositeData data =
+ new CompositeDataSupport(rowType, keyValue, descrValue);
+ convertedDescrMap.put(data);
+ }
+
+ Attribute descrAtt =
+ new Attribute("NotifDescriptorAsMapAtt", convertedDescrMap);
+ mbsc.setAttribute(objName, descrAtt);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Compare the Descriptor from"
+ + " the MBeanNotificationInfo against a reference");
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(objName);
+ errorCount += checkMBeanInfo(mbInfo, refNotifDescriptor);
+ System.out.println("---- DONE\n") ;
+
+ // ----
+ System.out.println("Check isInstanceOf(Basic)");
+
+ if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_CLASS_NAME) ) {
+ errorCount++;
+ System.out.println("---- ERROR isInstanceOf returned false\n") ;
+ } else {
+ System.out.println("---- OK\n") ;
+ }
+
+ // ----
+ System.out.println("Check isInstanceOf(BasicMXBean)");
+
+ if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_INTERFACE_NAME) ) {
+ errorCount++;
+ System.out.println("---- ERROR isInstanceOf returned false\n") ;
+ } else {
+ System.out.println("---- OK\n") ;
+ }
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Ask for "
+ + numOfNotifications + " notification(s)");
+ Object[] sendNotifParam = new Object[1];
+ String[] sendNotifSig = new String[]{"java.lang.String"};
+
+ for (int i = 0; i < numOfNotifications; i++) {
+ // Select which type of notification we ask for
+ if ( i % 2 == 0 ) {
+ sendNotifParam[0] = Basic.NOTIF_TYPE_0;
+ } else {
+ sendNotifParam[0] = Basic.NOTIF_TYPE_1;
+ }
+
+ // Trigger notification emission
+ mbsc.invoke(objName,
+ "sendNotification",
+ sendNotifParam,
+ sendNotifSig);
+
+ // Wait for it then check it when it comes early enough
+ Notification notif =
+ notifList.poll(timeForNotificationInSeconds,
+ TimeUnit.SECONDS) ;
+ // The very first notification is likely to come in slower than
+ // all the others. Because that test isn't targeting the speed
+ // notifications are delivered with, we prefer to secure it.
+ if (i == 0 && notif == null) {
+ System.out.println("MXBeanNotifTest::run: Wait extra "
+ + timeForNotificationInSeconds + " second(s) the "
+ + " very first notification");
+ notif = notifList.poll(timeForNotificationInSeconds,
+ TimeUnit.SECONDS);
+ }
+
+ if ( notif == null ) {
+ errorCount++;
+ System.out.println("---- ERROR No notification received"
+ + " within allocated " + timeForNotificationInSeconds
+ + " second(s) !");
+ } else {
+ errorCount +=
+ checkNotification(notif,
+ (String)sendNotifParam[0],
+ Basic.NOTIFICATION_MESSAGE,
+ objName);
+ }
+ }
+
+ int toc = 0;
+ while ( notifList.size() < 2 && toc < 10 ) {
+ Thread.sleep(499);
+ toc++;
+ }
+ System.out.println("---- DONE\n") ;
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanNotifTest::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanNotifTest::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+ }
+
+
+ private int checkMBeanInfo(MBeanInfo mbi, Descriptor refDescr) {
+ MBeanNotificationInfo[] notifsInfo = mbi.getNotifications();
+ int res = 0;
+
+ for (MBeanNotificationInfo mbni : notifsInfo) {
+ if ( mbni.getDescriptor().equals(refDescr) ) {
+ System.out.println("(OK)");
+ } else {
+ System.out.println("(ERROR) Descriptor of the notification is "
+ + mbni.getDescriptor()
+ + " as we expect "
+ + refDescr);
+ res++;
+ }
+ }
+
+ return res;
+ }
+
+
+ private int checkNotification(Notification notif,
+ String refType,
+ String refMessage,
+ ObjectName refSource) {
+ int res = 0;
+
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getSource " + notif.getSource());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getMessage " + notif.getMessage());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getSequenceNumber " + notif.getSequenceNumber());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getTimeStamp " + notif.getTimeStamp());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getType " + notif.getType());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getUserData " + notif.getUserData());
+
+ if ( ! notif.getType().equals(refType) ) {
+ res++;
+ System.out.println("(ERROR) Type is not "
+ + refType + " in notification\n" + notif);
+ } else {
+ if ( notif.getType().equals(Basic.NOTIF_TYPE_0)
+ && ! (notif instanceof javax.management.Notification) ) {
+ res++;
+ System.out.println("(ERROR) Notification is not instance of "
+ + " javax.management.Notification but rather "
+ + notif.getClass().getName());
+ } else if ( notif.getType().equals(Basic.NOTIF_TYPE_1)
+ && ! (notif instanceof SqeNotification) ) {
+ res++;
+ System.out.println("(ERROR) Notification is not instance of "
+ + " javasoft.sqe.jmx.share.SqeNotification but rather "
+ + notif.getClass().getName());
+ }
+ }
+
+ if ( ! notif.getMessage().equals(refMessage) ) {
+ res++;
+ System.out.println("(ERROR) Message is not "
+ + refMessage + " in notification\n" + notif);
+ }
+
+ if ( ! notif.getSource().equals(refSource) ) {
+ res++;
+ System.out.println("(ERROR) Source is not "
+ + refSource + " in notification\n" + notif);
+ }
+
+ return res;
+ }
+
+ public void handleNotification(Notification notification, Object handback) {
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "MXBeanNotifTest::handleNotification: Received "
+ + notification);
+ notifList.add(notification);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanWeirdParamTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2005, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks that a serialized instance is not transmitted from an MXBean.
+ * All the communication should be done via Open Types
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Basic.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanWeirdParamTest
+ */
+
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import java.lang.Process;
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JDKToolFinder;
+
+public class MXBeanWeirdParamTest {
+
+ private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
+
+ private static final String CLIENT_CLASS_MAIN =
+ "MXBeanWeirdParamTest$ClientSide";
+
+ private JMXConnectorServer cs;
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanWeirdParamTest test = new MXBeanWeirdParamTest();
+ test.run(map);
+
+ }
+
+ /*
+ * Create the MBeansServe side of the test and returns its address
+ */
+ private JMXServiceURL createServerSide() throws Exception {
+ final int NINETY_SECONDS = 90;
+
+ // We will use the platform mbean server
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ Utils.waitReady(cs, NINETY_SECONDS);
+
+ JMXServiceURL addr = cs.getAddress();
+ return addr;
+ }
+
+
+ /*
+ * Creating command-line for running subprocess JVM:
+ *
+ * JVM command line is like:
+ * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
+ *
+ * {defaultopts} are the default java options set by the framework.
+ *
+ */
+ private List<String> buildCommandLine() {
+ List<String> opts = new ArrayList<>();
+ opts.add(JDKToolFinder.getJDKTool("java"));
+ opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts()));
+ // We need to set WEIRD_PARAM propertty on the client-side
+ opts.add("-DWEIRD_PARAM");
+ opts.add("-cp");
+ opts.add(System.getProperty("test.class.path", "test.class.path"));
+ opts.add(CLIENT_CLASS_MAIN);
+
+ return opts;
+ }
+
+ /**
+ * Runs MXBeanWeirdParamTest$ClientSide with the passed options and redirects
+ * subprocess standard I/O to the current (parent) process. This provides a
+ * trace of what happens in the subprocess while it is runnning (and before
+ * it terminates).
+ *
+ * @param serviceUrlStr string representing the JMX service Url to connect to.
+ */
+ private int runClientSide(String serviceUrlStr) throws Exception {
+
+ // Building command-line
+ List<String> opts = buildCommandLine();
+ opts.add(serviceUrlStr);
+
+ // Launch separate JVM subprocess
+ int exitCode = 0;
+ String[] optsArray = opts.toArray(new String[0]);
+ ProcessBuilder pb = new ProcessBuilder(optsArray);
+ Process p = ProcessTools.startProcess("MXBeanWeirdParamTest$ClientSide", pb);
+
+ // Handling end of subprocess
+ try {
+ exitCode = p.waitFor();
+ if (exitCode != 0) {
+ System.out.println(
+ "Subprocess unexpected exit value of [" + exitCode +
+ "]. Expected 0.\n");
+ }
+ } catch (InterruptedException e) {
+ System.out.println("Parent process interrupted with exception : \n " + e + " :" );
+
+ // Parent thread unknown state, killing subprocess.
+ p.destroyForcibly();
+
+ throw new RuntimeException(
+ "Parent process interrupted with exception : \n " + e + " :" );
+ } finally {
+ return exitCode;
+ }
+
+ }
+
+ public void run(Map<String, Object> args) throws Exception {
+
+ System.out.println("MXBeanWeirdParamTest::run: Start") ;
+ int errorCount = 0;
+
+ try {
+ // Initialise the server side
+ JMXServiceURL urlToUse = createServerSide();
+
+ // Run client side
+ errorCount = runClientSide(urlToUse.toString());
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanWeirdParamTest::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanWeirdParamTest::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+
+ cs.stop();
+
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private static class ClientSide {
+ public static void main(String args[]) throws Exception {
+
+ int errorCount = 0 ;
+ String msgTag = "ClientSide::main: ";
+
+ try {
+
+ // Get a connection to remote mbean server
+ JMXServiceURL addr = new JMXServiceURL(args[0]);
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // ----
+ System.out.println(msgTag + "Create and register the MBean");
+ ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
+ mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
+ System.out.println(msgTag +"---- OK\n") ;
+
+ // ----
+ System.out.println(msgTag +"Get attribute SqeParameterAtt on our MXBean");
+ Object result = mbsc.getAttribute(objName, "SqeParameterAtt");
+ System.out.println(msgTag +"(OK) Got result of class "
+ + result.getClass().getName());
+ System.out.println(msgTag +"Received CompositeData is " + result);
+ System.out.println(msgTag +"---- OK\n") ;
+
+ // ----
+ // We use the value returned by getAttribute to perform the invoke.
+ System.out.println(msgTag +"Call operation doWeird on our MXBean [1]");
+ mbsc.invoke(objName, "doWeird",
+ new Object[]{result},
+ new String[]{"javax.management.openmbean.CompositeData"});
+ System.out.println(msgTag +"---- OK\n") ;
+
+ // ----
+ // We build the CompositeData ourselves that time.
+ System.out.println(msgTag +"Call operation doWeird on our MXBean [2]");
+ String typeName = "SqeParameter";
+ String[] itemNames = new String[] {"glop"};
+ OpenType<?>[] openTypes = new OpenType<?>[] {SimpleType.STRING};
+ CompositeType rowType = new CompositeType(typeName, typeName,
+ itemNames, itemNames, openTypes);
+ Object[] itemValues = {"HECTOR"};
+ CompositeData data =
+ new CompositeDataSupport(rowType, itemNames, itemValues);
+ TabularType tabType = new TabularType(typeName, typeName,
+ rowType, new String[]{"glop"});
+ TabularDataSupport tds = new TabularDataSupport(tabType);
+ tds.put(data);
+ System.out.println(msgTag +"Source CompositeData is " + data);
+ mbsc.invoke(objName, "doWeird",
+ new Object[]{data},
+ new String[]{"javax.management.openmbean.CompositeData"});
+ System.out.println(msgTag +"---- OK\n") ;
+
+ // ----
+ System.out.println(msgTag +"Unregister the MBean");
+ mbsc.unregisterMBean(objName);
+ System.out.println(msgTag +"---- OK\n") ;
+
+ // Terminate the JMX Client
+ cc.close();
+
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ throw new RuntimeException(e);
+ } finally {
+ System.exit(errorCount);
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/SqeDescriptorKey.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005, 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.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.management.DescriptorKey;
+
+/**
+ * That annotation is usable everywhere DescriptorKey is (and even more).
+ * It is for use to test that you can retrieve the SqeDescriptorKey into the
+ * appropriate Descriptor instances as built by the JMX runtime.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SqeDescriptorKey {
+ @DescriptorKey("sqeDescriptorKey")
+ String value();
+
+ // List descriptor fields that may be added or may be updated
+ // when retrieving an MBeanInfo using a JMXWS connection compared to the
+ // MBeanInfo returned by a local MBeanServer.
+ // The annotation format is :
+ // <descriptorFieldName>=<descriptorFieldValue>
+ // The values actually handled by the test suite are :
+ // openType=SimpleType.VOID
+ @DescriptorKey("descriptorFields")
+ String[] descriptorFields() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/SqeNotification.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2005, 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 javax.management.Notification;
+
+/**
+ * Could hold someday a specific semantic.
+ * For now it is used to have a Notification which of another class, no more.
+ */
+public class SqeNotification extends Notification {
+
+ /** Creates a new instance of SqeNotification */
+ public SqeNotification(String type, Object source, long sequenceNumber) {
+ super(type, source, sequenceNumber);
+ }
+
+ /** Creates a new instance of SqeNotification */
+ public SqeNotification(String type, Object source, long sequenceNumber,
+ long timeStamp) {
+ super(type, source, sequenceNumber, timeStamp);
+ }
+
+ /** Creates a new instance of SqeNotification */
+ public SqeNotification(String type, Object source, long sequenceNumber,
+ long timeStamp, String message) {
+ super(type, source, sequenceNumber, timeStamp, message);
+ }
+
+ /** Creates a new instance of SqeNotification */
+ public SqeNotification(String type, Object source, long sequenceNumber,
+ String message) {
+ super(type, source, sequenceNumber, message);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/SqeParameter.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005, 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.io.Serializable;
+
+/**
+ * That class is to use as an MBean operation parameter or returned value.
+ * The property Glop with its public getter + setter is only there to be
+ * reconstructible following MXBean specification, so that SqeParameter can be
+ * used for what it is designed to.
+ */
+public class SqeParameter implements Serializable {
+
+ private static boolean weird;
+ private String glop;
+
+ static {
+ if ( System.getProperty("WEIRD_PARAM") != null ) {
+ weird = true;
+ }
+ }
+
+ /**
+ * Creates a new instance of SqeParameter.
+ * <br>When the Java property WEIRD_PARAM is set, that constructor
+ * throws an exception.
+ * <br>That can be used to ensure the class is instantiated on server side
+ * but never on client side.
+ */
+ public SqeParameter() throws Exception {
+ if ( weird ) {
+ throw new Exception();
+ }
+ }
+
+ public String getGlop() {
+ return glop;
+ }
+
+ public void setGlop(String value) {
+ glop = value;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/Utils.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2005, 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.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.lang.reflect.Method;
+import javax.management.remote.JMXConnectorServerMBean;
+
+// utility class for MXBean* tests coming from JMX Tonga test suite
+class Utils {
+
+ // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property
+ private static final String DEBUG_HEADER = "[debug] ";
+
+ // DEBUG levels
+ private static int selectedDebugLevel = 0;
+ static final int DEBUG_STANDARD = 1;
+ static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests
+ static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE;
+
+ static void parseDebugProperties() {
+ int level = 0;
+ Properties p = System.getProperties();
+
+ // get selected levels
+ if (p.getProperty("DEBUG_STANDARD") != null) {
+ level |= DEBUG_STANDARD;
+ }
+
+ if (p.getProperty("DEBUG_VERBOSE") != null) {
+ level |= DEBUG_VERBOSE;
+ }
+
+ if (p.getProperty("DEBUG_ALL") != null) {
+ level |= DEBUG_ALL;
+ }
+
+ selectedDebugLevel = level;
+ }
+
+ /**
+ * Reproduces the original parsing and collection of test parameters
+ * from the DTonga JMX test suite.
+ *
+ * Collects passed args and returns them in a map(argname, value) structure,
+ * which will be then propagated as necessary to various called methods.
+ */
+ static Map<String, Object> parseParameters(String args[])
+ throws Exception {
+ Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start");
+ HashMap<String, Object> map = new HashMap<>();
+
+ for ( int i = 0; i < args.length; i++ ) {
+ if ( args[i].trim().startsWith("-") ) {
+ if ((i+1) < args.length && !args[i+1].startsWith("-") ) {
+ Utils.debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with value " +
+ args[i+1]) ;
+ map.put(args[i].trim(), args[i+1].trim()) ;
+ } else if ((i+1) < args.length && args[i+1].startsWith("-") ||
+ (i+1) == args.length ) {
+ Utils.debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with null value") ;
+ map.put(args[i].trim(), null) ;
+ } else {
+ System.out.println(
+ "TestRoot::parseParameters: (WARNING) not added in map = " +
+ args[i]) ;
+ }
+ }
+ }
+
+ Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ;
+ return map ;
+ }
+
+ /**
+ * This method is to be used in all tests to print anything
+ * that is temporary.
+ * Printing is done only when debug is activated by the property DEBUG.
+ * Printing depends also on the DEBUG_LEVEL property.
+ * Here it encapsulates a System.out.println.
+ */
+ public static void debug(int level, String line) {
+ if ((selectedDebugLevel & level) != 0) {
+ System.out.println(DEBUG_HEADER + line);
+ }
+ }
+
+ /**
+ * Do print stack trace when withStack is true.
+ * Does try to call getTargetException() and getTargetError() then
+ * print embedded stacks in the case of an Exception wrapping
+ * another Exception or an Error. Recurse until no more wrapping
+ * is found.
+ */
+ public static void printThrowable(Throwable theThro, boolean withStack) {
+ try {
+ if (withStack) {
+ theThro.printStackTrace(System.out);
+ }
+ if (theThro instanceof Exception) {
+ Exception t = (Exception) theThro;
+ Method target = null;
+ String blank = " ";
+ try {
+ target = t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not
+ }
+ System.out.println(blank + t.getClass() + "==>" + t.getMessage());
+ while (target != null) {
+ try {
+ t = (Exception) target.invoke(t,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ t = null;
+ }
+ try {
+ if (t != null) {
+ blank = blank + " ";
+ System.out.println(blank + t.getClass() + "==>" +
+ t.getMessage());
+ try {
+ target =
+ t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not }
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+
+ // We may have exceptions wrapping an Error then it is
+ // getTargetError that is likely to be called
+ try {
+ target = ((Exception) theThro).getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ Throwable err = theThro;
+ while (target != null) {
+ try {
+ err = (Error) target.invoke(err,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ err = null;
+ }
+ try {
+ if (err != null) {
+ blank = blank + " ";
+ System.out.println(blank + err.getClass() + "==>" +
+ err.getMessage());
+ if (withStack) {
+ err.printStackTrace(System.out);
+ }
+ try {
+ target = err.getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+ } else {
+ System.out.println("Throwable is : " + theThro);
+ }
+ } catch (Throwable x) {
+ System.out.println("Exception : raised in printException : " + x);
+ }
+ }
+
+ /**
+ * Wait up to maxTimeInSeconds second(s) the given JMX connector server
+ * comes up (which means isActive returns true).
+ * If it fails to do so we throw a RunTime exception.
+ */
+ public static void waitReady(JMXConnectorServerMBean server,
+ int maxTimeInSeconds) throws Exception {
+ int elapsed = 0;
+
+ while (!server.isActive() && elapsed < maxTimeInSeconds) {
+ Thread.sleep(1000);
+ elapsed++;
+ }
+
+ if (server.isActive()) {
+ String message = "Utils::waitReady: JMX connector server came up";
+ if ( elapsed == 0) {
+ message += " immediately";
+ } else {
+ message += " after " + elapsed + " seconds";
+ }
+ message += " [" + server.getAddress() + "]";
+ Utils.debug(DEBUG_STANDARD, message);
+ } else {
+ String message = "Utils::waitReady: (ERROR) JMX connector" +
+ " server didn't come up after " + elapsed + " seconds [" +
+ server.getAddress() + "]";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/QueryData.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006, 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.
+ */
+
+public abstract class QueryData {
+ protected int intValue = 9;
+ protected long longValue = 9L;
+ protected Integer integerValue = Integer.valueOf(9);
+ protected boolean booleanValue = true;
+ protected double doubleValue = 9D;
+ protected float floatValue = 9.0F;
+ protected String stringValue = "9";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/QueryFactory.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2006, 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.util.ArrayList;
+
+import javax.management.Query;
+import javax.management.QueryExp;
+import javax.management.ValueExp;
+
+/**
+ * Class used for building QueryExp instances of all every possible type
+ * in terms of JMX API members; note that several JMX classes are private
+ * and appears in the JDK API only by their serial form.
+ * Comments in each case of the big switch in method getQuery() details which
+ * API member we cover with a given query.
+ */
+public class QueryFactory extends QueryData {
+
+ private String mbeanClassName = "";
+ private String primitiveIntAttName = "IntAtt";
+ private String primitiveLongAttName = "LongAtt";
+ private String integerAttName = "IntegerAtt";
+ private String primitiveBooleanAttName = "BooleanAtt";
+ private String primitiveDoubleAttName = "DoubleAtt";
+ private String primitiveFloatAttName = "FloatAtt";
+ private String stringAttName = "StringAtt";
+ private ArrayList<QueryExp> queries = new ArrayList<QueryExp>();
+
+ /**
+ * Creates a new instance of QueryFactory.
+ * The name is the fully qualified class name of an MBean.
+ * There is severe constraints on that MBean that must:
+ * <ul>
+ * <li>extend QueryData in order to inherit attribute values.
+ * <li>define a RW attribute IntAtt of type int
+ * initialized to QueryData.longValue
+ * <li>define a RW attribute LongAtt of type long
+ * initialized to QueryData.intValue
+ * <li>define a RW attribute IntegerAtt of type Integer
+ * initialized to QueryData.integerValue
+ * <li>define a RW attribute BooleanAtt of type boolean
+ * initialized to QueryData.booleanValue
+ * <li>define a RW attribute DoubleAtt of type double
+ * initialized to QueryData.doubleValue
+ * <li>define a RW attribute FloatAtt of type float
+ * initialized to QueryData.floatValue
+ * <li>define a RW attribute StringAtt of type String
+ * initialized to QueryData.stringValue
+ * </ul>
+ */
+ public QueryFactory(String name) {
+ this.mbeanClassName = name;
+ }
+
+ /**
+ * Returns the highest index value the method getQuery supports.
+ * WARNING : returns 0 if buildQueries haven't been called first !
+ */
+ public int getSize() {
+ return queries.size();
+ }
+
+ /**
+ * Populates an ArrayList of QueryExp.
+ * Lowest index is 1.
+ * Highest index is returned by getSize().
+ * <br>The queries numbered 1 to 23 allow to cover all the underlying
+ * Java classes of the JMX API used to build queries.
+ */
+ public void buildQueries() {
+ if ( queries.size() == 0 ) {
+ int smallerIntValue = intValue - 1;
+ int biggerIntValue = intValue + 1;
+
+ // case 1:
+ // True if the MBean is of class mbeanClassName
+ // We cover javax.management.InstanceOfQueryExp
+ queries.add(Query.isInstanceOf(Query.value(mbeanClassName)));
+
+ // case 2:
+ // True if the MBean is of class mbeanClassName
+ // We cover javax.management.MatchQueryExp and
+ // javax.management.ClassAttributeValueExp
+ queries.add(Query.match(Query.classattr(),
+ Query.value(mbeanClassName)));
+
+ // case 3:
+ // True if an attribute named primitiveIntAttName of type int has
+ // the value intValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.NumericValueExp
+ queries.add(Query.eq(Query.attr(primitiveIntAttName),
+ Query.value(intValue)));
+
+ // case 4:
+ // True if an attribute named primitiveLongAttName of type long has
+ // the value longValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.NumericValueExp
+ queries.add(Query.eq(Query.attr(primitiveLongAttName),
+ Query.value(longValue)));
+
+ // case 5:
+ // True if an attribute named primitiveDoubleAttName of type double
+ // has the value doubleValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.NumericValueExp
+ queries.add(Query.eq(Query.attr(primitiveDoubleAttName),
+ Query.value(doubleValue)));
+
+ // case 6:
+ // True if an attribute named primitiveFloatAttName of type float
+ // has the value floatValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.NumericValueExp
+ queries.add(Query.eq(Query.attr(primitiveFloatAttName),
+ Query.value(floatValue)));
+
+ // case 7:
+ // True if an attribute named primitiveIntAttName of type int is
+ // hold by an MBean of class mbeanClassName and has
+ // the value intValue
+ // We cover javax.management.QualifiedAttributeValueExp
+ queries.add(Query.eq(Query.attr(mbeanClassName, primitiveIntAttName),
+ Query.value(intValue)));
+
+ // case 8:
+ // True if an attribute named stringAttName of type String has
+ // the value stringValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.StringValueExp
+ queries.add(Query.eq(Query.attr(stringAttName),
+ Query.value(stringValue)));
+
+ // case 9:
+ // True if an attribute named integerAttName of type Integer has
+ // the value integerValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.NumericValueExp
+ queries.add(Query.eq(Query.attr(integerAttName),
+ Query.value(integerValue)));
+
+ // case 10:
+ // True if an attribute named primitiveBooleanAttName of type boolean
+ // has the value booleanValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to EQ and javax.management.BooleanValueExp
+ queries.add(Query.eq(Query.attr(primitiveBooleanAttName),
+ Query.value(booleanValue)));
+
+ // case 11:
+ // True if an attribute named primitiveIntAttName of type int has
+ // not the value smallerIntValue
+ // We cover javax.management.NotQueryExp
+ queries.add(Query.not(Query.eq(Query.attr(primitiveIntAttName),
+ Query.value(smallerIntValue))));
+
+ // case 12:
+ // True if either
+ // an attribute named primitiveIntAttName of type int has
+ // the value intValue
+ // or
+ // an attribute named primitiveLongAttName of type long has
+ // the value longValue
+ // We cover javax.management.OrQueryExp
+ queries.add(Query.or(
+ Query.eq(Query.attr(primitiveIntAttName),
+ Query.value(intValue)),
+ Query.eq(Query.attr(primitiveLongAttName),
+ Query.value(longValue))));
+
+ // case 13:
+ // True if
+ // an attribute named primitiveIntAttName of type int has
+ // the value intValue
+ // and
+ // an attribute named primitiveLongAttName of type long has
+ // the value longValue
+ // We cover javax.management.AndQueryExp
+ queries.add(Query.and(
+ Query.eq(Query.attr(primitiveIntAttName),
+ Query.value(intValue)),
+ Query.eq(Query.attr(primitiveLongAttName),
+ Query.value(longValue))));
+
+ // case 14:
+ // True if an attribute named primitiveIntAttName of type int has
+ // the value intValue
+ // We cover javax.management.InQueryExp
+ ValueExp[] inArray = {Query.value(intValue)};
+ queries.add(Query.in(Query.attr(primitiveIntAttName), inArray));
+
+ // case 15:
+ // True if an attribute named primitiveIntAttName of type int has
+ // its value in between smallerIntValue and biggerIntValue
+ // We cover javax.management.BetweenRelQueryExp
+ queries.add(Query.between(Query.attr(primitiveIntAttName),
+ Query.value(smallerIntValue),
+ Query.value(biggerIntValue)));
+
+ // case 16:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value greater than smallerIntValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to GT
+ queries.add(Query.gt(Query.attr(primitiveIntAttName),
+ Query.value(smallerIntValue)));
+
+ // case 17:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value greater or equal to smallerIntValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to GE
+ queries.add(Query.geq(Query.attr(primitiveIntAttName),
+ Query.value(smallerIntValue)));
+
+ // case 18:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value smaller than biggerIntValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to LT
+ queries.add(Query.lt(Query.attr(primitiveIntAttName),
+ Query.value(biggerIntValue)));
+
+ // case 19:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value smaller or equal to biggerIntValue
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to LE
+ queries.add(Query.leq(Query.attr(primitiveIntAttName),
+ Query.value(biggerIntValue)));
+
+ // case 20:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value equal to intValue minus zero
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to MINUS
+ queries.add(Query.eq(Query.attr(primitiveIntAttName),
+ Query.minus(Query.value(intValue), Query.value(0))));
+
+ // case 21:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value equal to intValue plus zero
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to PLUS
+ queries.add(Query.eq(Query.attr(primitiveIntAttName),
+ Query.plus(Query.value(intValue), Query.value(0))));
+
+ // case 22:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value equal to intValue divided by one
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to DIV
+ queries.add(Query.eq(Query.attr(primitiveIntAttName),
+ Query.div(Query.value(intValue), Query.value(1))));
+
+ // case 23:
+ // True if an attribute named primitiveIntAttName of type int has
+ // a value equal to intValue multiplicated by one
+ // We cover javax.management.BinaryRelQueryExp with
+ // a relOp equal to TIMES
+ queries.add(Query.eq(Query.attr(primitiveIntAttName),
+ Query.times(Query.value(intValue), Query.value(1))));
+
+ // case 24:
+ // That query is a complex one that combines within a big AND
+ // queries with index 2 to 23 inclusive. But because a List is
+ // zero based, we must decrement all indexes by 1 when retrieving
+ // any previously stored query.
+ QueryExp q2_3 = Query.and(queries.get(2-1), queries.get(3-1));
+ QueryExp q4_5 = Query.and(queries.get(4-1), queries.get(5-1));
+ QueryExp q6_7 = Query.and(queries.get(6-1), queries.get(7-1));
+ QueryExp q8_9 = Query.and(queries.get(8-1), queries.get(9-1));
+ QueryExp q10_11 = Query.and(queries.get(10-1), queries.get(11-1));
+ QueryExp q12_13 = Query.and(queries.get(12-1), queries.get(13-1));
+ QueryExp q14_15 = Query.and(queries.get(14-1), queries.get(15-1));
+ QueryExp q16_17 = Query.and(queries.get(16-1), queries.get(17-1));
+ QueryExp q18_19 = Query.and(queries.get(18-1), queries.get(19-1));
+ QueryExp q20_21 = Query.and(queries.get(20-1), queries.get(21-1));
+ QueryExp q22_23 = Query.and(queries.get(22-1), queries.get(23-1));
+ QueryExp q2_5 = Query.and(q2_3, q4_5);
+ QueryExp q6_9 = Query.and(q6_7, q8_9);
+ QueryExp q10_13 = Query.and(q10_11, q12_13);
+ QueryExp q14_17 = Query.and(q14_15, q16_17);
+ QueryExp q18_21 = Query.and(q18_19, q20_21);
+ QueryExp q2_9 = Query.and(q2_5, q6_9);
+ QueryExp q10_17 = Query.and(q10_13, q14_17);
+ QueryExp q18_23 = Query.and(q18_21, q22_23);
+ QueryExp q2_17 = Query.and(q2_9, q10_17);
+ queries.add(Query.and(q2_17, q18_23));
+
+ // case 25:
+ // Complex query mixing AND and OR.
+ queries.add(Query.or(q6_9, q18_23));
+ }
+ }
+
+ /**
+ * Returns a QueryExp taken is the ArrayList populated by buildQueries().
+ * Lowest index is 1.
+ * Highest index is returned by getSize().
+ * <br>The queries numbered 1 to 23 allow to cover all the underlying
+ * Java classes of the JMX API used to build queries.
+ */
+ public QueryExp getQuery(int index) {
+ return queries.get(index - 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/ServerDelegate.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2004, 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.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.remote.JMXServiceURL ;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+/**
+ * This class defines an MBean that can be registered and used on client side
+ * to handle informations or properties of the remote server.
+ *
+ * For example, this MBean can store IOR addresses
+ * of RMI/IIOP connector(s) used in a test.
+ *
+ * That MBean might not be used for testing purpose itself.
+ */
+public class ServerDelegate implements ServerDelegateMBean, MBeanRegistration {
+
+ private MBeanServer mbeanServer = null;
+ private List<JMXServiceURL> addresses = null;
+ private String port;
+ private static String javaVersion = System.getProperty("java.version");
+ private int sqeJmxwsCredentialsProviderCallCount = 0;
+ private String jmxwsCredentialsProviderUrl = null;
+ private int testJMXAuthenticatorCallCount = 0;
+ private Principal testJMXAuthenticatorPrincipal = null;
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR ServerDelegate")
+ public ServerDelegate() {
+ addresses = new ArrayList<JMXServiceURL>();
+ }
+
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ // Initialize MBeanServer attribute
+ mbeanServer = server;
+ return name;
+ }
+ public void postRegister(Boolean registrationDone) {
+ }
+ public void preDeregister() throws Exception {
+ }
+ public void postDeregister() {
+ }
+
+ public void addAddress(JMXServiceURL url) {
+ addresses.add(url) ;
+ }
+
+ public List<JMXServiceURL> getAddresses() {
+ return addresses ;
+ }
+
+ public void setPort(String p) {
+ port = p ;
+ }
+
+ public String getPort() {
+ return port ;
+ }
+
+ public String getJavaVersion() {
+ return javaVersion;
+ }
+
+ public void sqeJmxwsCredentialsProviderCalled() {
+ sqeJmxwsCredentialsProviderCallCount++;
+ }
+
+ public int getSqeJmxwsCredentialsProviderCallCount() {
+ return sqeJmxwsCredentialsProviderCallCount;
+ }
+
+ public void setJmxwsCredentialsProviderUrl(String url) {
+ jmxwsCredentialsProviderUrl = url;
+ }
+
+ public String getJmxwsCredentialsProviderUrl() {
+ return jmxwsCredentialsProviderUrl;
+ }
+
+ public void testJMXAuthenticatorCalled() {
+ testJMXAuthenticatorCallCount++;
+ }
+
+ public int getTestJMXAuthenticatorCallCount() {
+ return testJMXAuthenticatorCallCount;
+ }
+
+ public void setTestJMXAuthenticatorPrincipal(Principal principal) {
+ testJMXAuthenticatorPrincipal = principal;
+ }
+
+ public String getTestJMXAuthenticatorPrincipalString() {
+ if ( testJMXAuthenticatorPrincipal != null ) {
+ return testJMXAuthenticatorPrincipal.toString();
+ }
+
+ return null;
+ }
+
+ /**
+ * Instantiates and registers a StandardMBean in the MBean server.
+ *
+ * @param implementationClassName
+ * The implementation class name of the MBean.
+ * @param interfaceClassName
+ * The management interface class name of the MBean.
+ * @param isMXBean
+ * If true, the resultant MBean is an MXBean.
+ * @param name
+ * The object name of the StandardMBean.
+ */
+ @SuppressWarnings("unchecked")
+ public void createStandardMBean(
+ String implementationClassName,
+ String interfaceClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception {
+
+ Object implementation =
+ Class.forName(implementationClassName).newInstance();
+ Class<Object> interfaceClass = interfaceClassName == null ? null :
+ (Class<Object>)Class.forName(interfaceClassName);
+
+ // Create the StandardMBean
+ StandardMBean standardMBean = new StandardMBean(
+ implementation,
+ interfaceClass,
+ isMXBean);
+
+ // Register the StandardMBean
+ mbeanServer.registerMBean(standardMBean, name);
+ }
+
+ /**
+ * Instantiates and registers a StandardMBean in the MBean server.
+ * The object will use standard JMX design pattern to determine
+ * the management interface associated with the given implementation.
+ */
+ @SuppressWarnings("unchecked")
+ public void createStandardMBean(
+ String implementationClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception {
+
+ createStandardMBean(implementationClassName, null, isMXBean, name);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/ServerDelegateMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2004, 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.security.Principal;
+import java.util.List;
+
+import javax.management.remote.JMXServiceURL ;
+import javax.management.ObjectName;
+
+@SqeDescriptorKey("INTERFACE ServerDelegateMBean")
+public interface ServerDelegateMBean {
+ @SqeDescriptorKey("ATTRIBUTE Address")
+ public void addAddress(JMXServiceURL url);
+
+ @SqeDescriptorKey("ATTRIBUTE Address")
+ public List<JMXServiceURL> getAddresses();
+
+ public String getPort();
+ public void setPort(String p);
+
+ public String getJavaVersion();
+
+ public void sqeJmxwsCredentialsProviderCalled();
+ public int getSqeJmxwsCredentialsProviderCallCount();
+
+ public void setJmxwsCredentialsProviderUrl(String url);
+ public String getJmxwsCredentialsProviderUrl();
+
+ public void testJMXAuthenticatorCalled();
+ public int getTestJMXAuthenticatorCallCount();
+
+ public void setTestJMXAuthenticatorPrincipal(Principal principal);
+ public String getTestJMXAuthenticatorPrincipalString();
+
+ public void createStandardMBean(
+ String implementationClassName,
+ String interfaceClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception;
+
+ public void createStandardMBean(
+ String implementationClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/SqeDescriptorKey.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005, 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.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.management.DescriptorKey;
+
+/**
+ * That annotation is usable everywhere DescriptorKey is (and even more).
+ * It is for use to test that you can retrieve the SqeDescriptorKey into the
+ * appropriate Descriptor instances as built by the JMX runtime.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SqeDescriptorKey {
+ @DescriptorKey("sqeDescriptorKey")
+ String value();
+
+ // List descriptor fields that may be added or may be updated
+ // when retrieving an MBeanInfo using a JMXWS connection compared to the
+ // MBeanInfo returned by a local MBeanServer.
+ // The annotation format is :
+ // <descriptorFieldName>=<descriptorFieldValue>
+ // The values actually handled by the test suite are :
+ // openType=SimpleType.VOID
+ @DescriptorKey("descriptorFields")
+ String[] descriptorFields() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/SupportedQueryTypesTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2006, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Tests most of the existing query types.
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @compile TestQuery.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SupportedQueryTypesTest -mbeanClassName TestQuery
+ */
+
+import java.util.Map ;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.lang.reflect.Method;
+
+import java.lang.management.ManagementFactory;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName ;
+import javax.management.QueryExp;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+public class SupportedQueryTypesTest {
+
+ protected String mbeanClassName = null;
+
+ private MBeanServerConnection mbsc = null;
+
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ SupportedQueryTypesTest test = new SupportedQueryTypesTest();
+ test.run(map);
+
+ }
+
+ public void run(Map<String, Object> args) {
+ int errorCount = 0;
+
+ ObjectName on = null;
+ ObjectName serverDelegateObjectName = null;
+
+ JMXConnectorServer cs = null;
+ JMXConnector cc = null;
+
+ System.out.println("SupportedQueryTypesTest::run: Start") ;
+ try {
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ cc = JMXConnectorFactory.connect(addr);
+ mbsc = cc.getMBeanServerConnection();
+
+
+ // Create and register the ServerDelegate MBean on the remote MBeanServer
+ String serverDelegateClassName = ServerDelegate.class.getName();
+ serverDelegateObjectName =
+ new ObjectName("defaultDomain:class=" + serverDelegateClassName);
+ mbsc.createMBean(serverDelegateClassName, serverDelegateObjectName);
+
+ // Retrieve the MBean class name
+ mbeanClassName = (String) args.get("-mbeanClassName") ;
+ on = new ObjectName("defaultDomain:class=" + mbeanClassName);
+
+ // Create and register the MBean on the remote MBeanServer
+ System.out.println("SupportedQueryTypesTest::run: CREATE " +
+ mbeanClassName + " on the remote MBeanServer with name "
+ + on);
+ mbsc.createMBean(mbeanClassName, on);
+
+ // Create a QueryFactory and setup which query we'll use.
+ QueryFactory queries = new QueryFactory(mbeanClassName);
+ queries.buildQueries();
+ int maxIndex = queries.getSize();
+ int minIndex = 1;
+
+ // Create a reference Set<ObjectName> to check later on
+ // the queryNames() results
+ Set<ObjectName> referenceNameSet = new HashSet<ObjectName>();
+ referenceNameSet.add(on);
+
+ // Create a reference Set<ObjectInstance> to check later on
+ // the queryMBeans() results
+ ObjectInstance oi = new ObjectInstance(on, mbeanClassName);
+ Set<ObjectInstance> referenceInstanceSet =
+ new HashSet<ObjectInstance>();
+ referenceInstanceSet.add(oi);
+
+ // Perform the queryNames and queryMBeans requests
+ for (int i = minIndex; i <= maxIndex; i++ ) {
+ QueryExp query = queries.getQuery(i);
+ System.out.println("----");
+ System.out.println("SupportedQueryTypesTest::run: Query # " + i);
+ System.out.println("query " + query);
+ errorCount +=
+ doQueryNames(query, referenceNameSet);
+ errorCount +=
+ doQueryMBeans(query, referenceInstanceSet);
+ }
+
+ } catch(Exception e) {
+ Utils.printThrowable(e, true);
+ errorCount++;
+
+ } finally {
+ // Do unregister the MBean
+ try {
+ if (mbsc.isRegistered(on)) {
+ mbsc.unregisterMBean(on);
+ }
+ if (mbsc.isRegistered(serverDelegateObjectName)) {
+ mbsc.unregisterMBean(serverDelegateObjectName);
+ }
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ }
+
+ try {
+ // Close JMX Connector Client
+ cc.close();
+ // Stop connertor server
+ cs.stop();
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ }
+ }
+
+ System.out.println("");
+ System.out.println("SupportedQueryTypesTest::run: Done") ;
+
+ // Handle result
+ if (errorCount == 0) {
+ System.out.println("SupportedQueryTypesTest::run: (OK)");
+ } else {
+ String message = "SupportedQueryTypesTest::run: (ERROR) Got " +
+ + errorCount + " error(s)";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+
+
+ private int doQueryNames(QueryExp query, Set<ObjectName> referenceSet) {
+ int errorCount = 0;
+ System.out.println(" <*> Perform queryNames call ");
+
+ try {
+ // Call queryNames on the remote MBeanServer
+ Set<ObjectName> remoteSet = mbsc.queryNames(null, query);
+
+ // Compare the 2 Set<ObjectName>
+ errorCount += checkSet(remoteSet, referenceSet);
+
+ // Cleaning
+ remoteSet.clear();
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true);
+ errorCount++;
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("\t(OK)");
+ } else {
+ System.out.println("\t(ERROR) Query failed");
+ }
+
+ return errorCount;
+ }
+
+
+ private int doQueryMBeans(QueryExp query, Set<ObjectInstance> referenceSet) {
+ int errorCount = 0;
+ System.out.println(" <*> Perform queryMBeans call ");
+
+ try {
+ // Call queryMBeans on the remote MBeanServer
+ Set<ObjectInstance> remoteSet = mbsc.queryMBeans(null, query);
+
+ // Compare the 2 Set<ObjectInstance>
+ errorCount += checkSet(remoteSet, referenceSet);
+
+ // Cleaning
+ remoteSet.clear();
+
+ } catch (Exception e) {
+ Utils.printThrowable(e, true);
+ errorCount++;
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("\t(OK)");
+ } else {
+ System.out.println("\t(ERROR) Query failed");
+ }
+
+ return errorCount;
+ }
+
+ /**
+ * Pretty print of a Set content.
+ * When the Set isn't empty, toString() is called on each element.
+ * <br>The variable's name used to hold that Set is given via the setName
+ * parameter and used in the output.
+ */
+ private static void printSet(Set<?> printableSet, String setName) {
+ if ( printableSet.size() == 0 ) {
+ System.out.println("The Set " + setName + " is empty");
+ } else {
+ System.out.println("The Set " + setName + " contains :");
+
+ for (Iterator<?> it = printableSet.iterator(); it.hasNext();) {
+ Object elem = it.next();
+ System.out.println("\t" + elem.toString());
+ }
+ }
+ }
+
+
+ /**
+ * This method check the Set remoteSet is equal to
+ * the reference Set referenceSet,
+ * which means same size and content (order doesn't matter).
+ * <br>It returns 0 when the check is fine, otherwise 1.
+ */
+ private int checkSet(Set<?> remoteSet, Set<?> referenceSet) {
+ if ( ! remoteSet.equals(referenceSet) ) {
+ System.out.println("SupportedQueryTypesTest::checkSet:"
+ + " (ERROR) Set aren't as expected");
+ printSet(remoteSet, "remoteSet");
+ printSet(referenceSet, "referenceSet");
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ // Utility inner class coming from JMX Tonga test suite.
+ private static class Utils {
+
+ // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property
+ static final String DEBUG_HEADER = "[debug] ";
+
+ // DEBUG levels
+ static int selectedDebugLevel = 0;
+ static final int DEBUG_STANDARD = 1;
+ static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests
+ static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE;
+
+ static void parseDebugProperties() {
+ int level = 0;
+ Properties p = System.getProperties();
+
+ // get selected levels
+ if (p.getProperty("DEBUG_STANDARD") != null) {
+ level |= DEBUG_STANDARD;
+ }
+
+ if (p.getProperty("DEBUG_VERBOSE") != null) {
+ level |= DEBUG_VERBOSE;
+ }
+
+ if (p.getProperty("DEBUG_ALL") != null) {
+ level |= DEBUG_ALL;
+ }
+
+ selectedDebugLevel = level;
+ }
+
+ /**
+ * Reproduces the original parsing and collection of test parameters
+ * from the DTonga JMX test suite.
+ *
+ * Collects passed args and returns them in a map(argname, value) structure,
+ * which will be then propagated as necessary to various called methods.
+ */
+ static Map<String, Object> parseParameters(String args[])
+ throws Exception {
+ debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start");
+ HashMap<String, Object> map = new HashMap<>();
+
+ for ( int i = 0; i < args.length; i++ ) {
+ if ( args[i].trim().startsWith("-") ) {
+ if ((i+1) < args.length && !args[i+1].startsWith("-") ) {
+ debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with value " +
+ args[i+1]) ;
+ map.put(args[i].trim(), args[i+1].trim()) ;
+ } else if ((i+1) < args.length && args[i+1].startsWith("-") ||
+ (i+1) == args.length ) {
+ debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with null value") ;
+ map.put(args[i].trim(), null) ;
+ } else {
+ System.out.println(
+ "TestRoot::parseParameters: (WARNING) not added in map = " +
+ args[i]) ;
+ }
+ }
+ }
+
+ debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ;
+ return map ;
+ }
+
+ /**
+ * This method is to be used in all tests to print anything
+ * that is temporary.
+ * Printing is done only when debug is activated by the property DEBUG.
+ * Printing depends also on the DEBUG_LEVEL property.
+ * Here it encapsulates a System.out.println.
+ */
+ static void debug(int level, String line) {
+ if ((selectedDebugLevel & level) != 0) {
+ System.out.println(DEBUG_HEADER + line);
+ }
+ }
+
+ /**
+ * Do print stack trace when withStack is true.
+ * Does try to call getTargetException() and getTargetError() then
+ * print embedded stacks in the case of an Exception wrapping
+ * another Exception or an Error. Recurse until no more wrapping
+ * is found.
+ */
+ static void printThrowable(Throwable theThro, boolean withStack) {
+ try {
+ if (withStack) {
+ theThro.printStackTrace(System.out);
+ }
+ if (theThro instanceof Exception) {
+ Exception t = (Exception) theThro;
+ Method target = null;
+ String blank = " ";
+ try {
+ target = t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not
+ }
+ System.out.println(blank + t.getClass() + "==>" + t.getMessage());
+ while (target != null) {
+ try {
+ t = (Exception) target.invoke(t,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ t = null;
+ }
+ try {
+ if (t != null) {
+ blank = blank + " ";
+ System.out.println(blank + t.getClass() + "==>" +
+ t.getMessage());
+ try {
+ target =
+ t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not }
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+
+ // We may have exceptions wrapping an Error then it is
+ // getTargetError that is likely to be called
+ try {
+ target = ((Exception) theThro).getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ Throwable err = theThro;
+ while (target != null) {
+ try {
+ err = (Error) target.invoke(err,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ err = null;
+ }
+ try {
+ if (err != null) {
+ blank = blank + " ";
+ System.out.println(blank + err.getClass() + "==>" +
+ err.getMessage());
+ if (withStack) {
+ err.printStackTrace(System.out);
+ }
+ try {
+ target = err.getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+ } else {
+ System.out.println("Throwable is : " + theThro);
+ }
+ } catch (Throwable x) {
+ System.out.println("Exception : raised in printException : " + x);
+ }
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/TestQuery.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2006, 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.
+ */
+
+/**
+ * Class TestQuery
+ * MBean used for testing the types wired when using QueryExp.
+ * It is heavily linked to QueryFactory.
+ */
+public class TestQuery extends QueryData implements TestQueryMBean {
+
+ /**
+ * Attribute : BooleanAtt
+ */
+ private boolean booleanAtt = booleanValue;
+
+ /**
+ * Attribute : DoubleAtt
+ */
+ private double doubleAtt = doubleValue;
+
+ /**
+ * Attribute : FloatAtt
+ */
+ private float floatAtt = floatValue;
+
+ /**
+ * Attribute : IntAtt
+ */
+ private int intAtt = intValue;
+
+ /**
+ * Attribute : IntegerAtt
+ */
+ private Integer integerAtt = integerValue;
+
+ /**
+ * Attribute : LongAtt
+ */
+ private long longAtt = longValue;
+
+ /**
+ * Attribute : StringAtt
+ */
+ private String stringAtt = stringValue;
+
+ public TestQuery() {
+ }
+
+ /**
+ * Get Att of type boolean
+ */
+ public boolean getBooleanAtt() {
+ return booleanAtt;
+ }
+
+ /**
+ * Set Att of type boolean
+ */
+ public void setBooleanAtt(boolean value) {
+ booleanAtt = value;
+ }
+
+ /**
+ * Get Att of type double
+ */
+ public double getDoubleAtt() {
+ return doubleAtt;
+ }
+
+ /**
+ * Set Att of type double
+ */
+ public void setDoubleAtt(double value) {
+ doubleAtt = value;
+ }
+
+ /**
+ * Get Att of type float
+ */
+ public float getFloatAtt() {
+ return floatAtt;
+ }
+
+ /**
+ * Set Att of type float
+ */
+ public void setFloatAtt(float value) {
+ floatAtt = value;
+ }
+
+ /**
+ * Get Att of type int
+ */
+ public int getIntAtt() {
+ return intAtt;
+ }
+
+ /**
+ * Set Att of type int
+ */
+ public void setIntAtt(int value) {
+ intAtt = value;
+ }
+
+ /**
+ * Get Att of type Integer
+ */
+ public Integer getIntegerAtt() {
+ return integerAtt;
+ }
+
+ /**
+ * Set Att of type Integer
+ */
+ public void setIntegerAtt(Integer value) {
+ integerAtt = value;
+ }
+
+ /**
+ * Get Att of type long
+ */
+ public long getLongAtt() {
+ return longAtt;
+ }
+
+ /**
+ * Set Att of type long
+ */
+ public void setLongAtt(long value) {
+ longAtt = value;
+ }
+
+ /**
+ * Get Att of type String
+ */
+ public String getStringAtt() {
+ return stringAtt;
+ }
+
+ /**
+ * Set Att of type String
+ */
+ public void setStringAtt(String value) {
+ stringAtt = value;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/query/TestQueryMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2006, 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.
+ */
+
+/**
+ * Interface TestQueryMBean
+ * MBean used for testing the types wired when using QueryExp.
+ * It is heavily linked to QueryFactory.
+ */
+public interface TestQueryMBean
+{
+ /**
+ * Get Att of type boolean
+ */
+ public boolean getBooleanAtt();
+
+ /**
+ * Set Att of type boolean
+ */
+ public void setBooleanAtt(boolean value);
+
+ /**
+ * Get Att of type double
+ */
+ public double getDoubleAtt();
+
+ /**
+ * Set Att of type double
+ */
+ public void setDoubleAtt(double value);
+
+ /**
+ * Get Att of type float
+ */
+ public float getFloatAtt();
+
+ /**
+ * Set Att of type float
+ */
+ public void setFloatAtt(float value);
+
+ /**
+ * Get Att of type int
+ */
+ public int getIntAtt();
+
+ /**
+ * Set Att of type int
+ */
+ public void setIntAtt(int value);
+
+ /**
+ * Get Att of type Integer
+ */
+ public Integer getIntegerAtt();
+
+ /**
+ * Set Att of type Integer
+ */
+ public void setIntegerAtt(Integer value);
+
+ /**
+ * Get Att of type long
+ */
+ public long getLongAtt();
+
+ /**
+ * Set Att of type long
+ */
+ public void setLongAtt(long value);
+
+ /**
+ * Get Att of type String
+ */
+ public String getStringAtt();
+
+ /**
+ * Set Att of type String
+ */
+ public void setStringAtt(String value);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/AuthorizationTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2003, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks various authentication behavior from remote jmx client
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Simple.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username4 -Dpassword=password4 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedGetException -expectedSetException
+ * @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
+ */
+
+import java.io.File;
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory ;
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.Attribute ;
+import javax.management.ObjectName ;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JDKToolFinder;
+
+public class AuthorizationTest {
+
+ static final String SERVER_CLASS_NAME = "AuthorizationTest";
+ static final String CLIENT_CLASS_NAME = "AuthorizationTest$ClientSide";
+ static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME;
+
+ static final String USERNAME_PROPERTY = "username";
+ static final String PASSWORD_PROPERTY = "password";
+
+ private JMXConnectorServer cs;
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+
+ // Supported parameters list format is :
+ // "MainClass [-server <param-spec> ...] [-client <param-spec> ...]
+ // with <param-spec> either "-parami valuei" or "-parami"
+ HashMap<String, Object> serverMap = new HashMap<>() ;
+ int clientArgsIndex =
+ Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap);
+
+ // Extract and records client params
+ String[] clientParams = null;
+ if (clientArgsIndex < args.length) {
+ int clientParamsSize = args.length - clientArgsIndex;
+ clientParams = new String[clientParamsSize];
+ System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize);
+ } else {
+ clientParams = new String[0];
+ }
+
+ // Run test
+ AuthorizationTest test = new AuthorizationTest();
+ test.run(serverMap, clientParams);
+
+ }
+
+ /*
+ * Create the MBeansServer side of the test and returns its address
+ */
+ private JMXServiceURL createServerSide(Map<String, Object> serverMap)
+ throws Exception {
+ final int NINETY_SECONDS = 90;
+
+ System.out.println("AuthorizationTest::createServerSide: Start") ;
+
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+
+ // Creates connection environment from server side params
+ HashMap<String, Object> env = new HashMap<>();
+ String value = null;
+
+ if ((value = (String)serverMap.get("-mapType")) != null) {
+ if (value.contains("x.access.file")) {
+ String accessFileStr = System.getProperty("test.src") +
+ File.separator + "access.properties";
+ env.put("jmx.remote.x.access.file", accessFileStr);
+ System.out.println("Added " + accessFileStr + " file as jmx.remote.x.access.file");
+ }
+ if (value.contains("x.password.file")) {
+ String passwordFileStr = System.getProperty("test.src") +
+ File.separator + "password.properties";
+ env.put("jmx.remote.x.password.file", passwordFileStr);
+ System.out.println("Added " + passwordFileStr + " file as jmx.remote.x.password.file");
+ }
+ }
+
+ if (serverMap.containsKey("-populate")) {
+ String populateClassName = "Simple";
+ ObjectName on =
+ new ObjectName("defaultDomain:class=Simple");
+
+ Utils.debug(Utils.DEBUG_STANDARD, "create and register Simple MBean") ;
+ mbs.createMBean(populateClassName, on);
+ }
+
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ cs.start();
+
+ Utils.waitReady(cs, NINETY_SECONDS);
+
+ JMXServiceURL addr = cs.getAddress();
+
+ System.out.println("AuthorizationTest::createServerSide: Done.") ;
+
+ return addr;
+ }
+
+ /*
+ * Creating command-line for running subprocess JVM:
+ *
+ * JVM command line is like:
+ * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
+ *
+ * {defaultopts} are the default java options set by the framework.
+ *
+ */
+ private List<String> buildCommandLine(String args[]) {
+ List<String> opts = new ArrayList<>();
+ opts.add(JDKToolFinder.getJDKTool("java"));
+ opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts()));
+
+ String usernameValue = System.getProperty(USERNAME_PROPERTY);
+ if (usernameValue != null) {
+ opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue);
+ }
+ String passwordValue = System.getProperty(PASSWORD_PROPERTY);
+ if (passwordValue != null) {
+ opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue);
+ }
+
+ opts.add("-cp");
+ opts.add(System.getProperty("test.class.path", "test.class.path"));
+ opts.add(CLIENT_CLASS_MAIN);
+ opts.addAll(Arrays.asList(args));
+ return opts;
+ }
+
+ /**
+ * Runs AuthorizationTest$ClientSide with the passed options and redirects
+ * subprocess standard I/O to the current (parent) process. This provides a
+ * trace of what happens in the subprocess while it is runnning (and before
+ * it terminates).
+ *
+ * @param serviceUrlStr string representing the JMX service Url to connect to.
+ */
+ private int runClientSide(String args[], String serviceUrlStr) throws Exception {
+
+ // Building command-line
+ List<String> opts = buildCommandLine(args);
+ opts.add("-serviceUrl");
+ opts.add(serviceUrlStr);
+
+ // Launch separate JVM subprocess
+ int exitCode = 0;
+ String[] optsArray = opts.toArray(new String[0]);
+ ProcessBuilder pb = new ProcessBuilder(optsArray);
+ Process p = ProcessTools.startProcess("AuthorizationTest$ClientSide", pb);
+
+ // Handling end of subprocess
+ try {
+ exitCode = p.waitFor();
+ if (exitCode != 0) {
+ System.out.println(
+ "Subprocess unexpected exit value of [" + exitCode +
+ "]. Expected 0.\n");
+ }
+ } catch (InterruptedException e) {
+ System.out.println("Parent process interrupted with exception : \n " + e + " :" );
+
+ // Parent thread unknown state, killing subprocess.
+ p.destroyForcibly();
+
+ throw new RuntimeException(
+ "Parent process interrupted with exception : \n " + e + " :" );
+
+ } finally {
+ if (p.isAlive()) {
+ p.destroyForcibly();
+ }
+ return exitCode;
+ }
+
+ }
+
+ public void run(Map<String, Object> serverArgs, String clientArgs[]) {
+
+ System.out.println("AuthorizationTest::run: Start") ;
+ int errorCount = 0;
+
+ try {
+ // Initialise the server side
+ JMXServiceURL urlToUse = createServerSide(serverArgs);
+
+ // Run client side
+ errorCount = runClientSide(clientArgs, urlToUse.toString());
+
+ if ( errorCount == 0 ) {
+ System.out.println("AuthorizationTest::run: Done without any error") ;
+ } else {
+ System.out.println("AuthorizationTest::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+
+ cs.stop();
+
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private static class ClientSide {
+
+ private JMXConnector cc = null;
+ private MBeanServerConnection mbsc = null;
+
+ public static void main(String args[]) throws Exception {
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+
+ // Supported parameters list format is : "MainClass [-client <param-spec> ...]
+ // with <param-spec> either "-parami valuei" or "-parami"
+ HashMap<String, Object> clientMap = new HashMap<>() ;
+ Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap);
+
+ // Run test
+ ClientSide test = new ClientSide();
+ test.run(clientMap);
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ int errorCount = 0 ;
+
+ try {
+ boolean expectedCreateException =
+ (args.containsKey("-expectedCreateException")) ? true : false ;
+ boolean expectedGetException =
+ (args.containsKey("-expectedGetException")) ? true : false ;
+ boolean expectedSetException =
+ (args.containsKey("-expectedSetException")) ? true : false ;
+ boolean expectedInvokeException =
+ (args.containsKey("-expectedInvokeException")) ? true : false ;
+ // JSR262 (see bug 6440374)
+ // There is no special JSR262 protocol operation for connect.
+ // The first request sent initiate the connection.
+ // In the JSR262 current implementation, getDefaultDomain is sent to
+ // the server in order to get the server part of the connection ID.
+ // => the connection may fail if no access permission on get requests.
+ boolean expectedConnectException =
+ (args.containsKey("-expectedConnectException")) ? true : false ;
+ // Before connection,
+ // remove the element of the Map with null values (not supported by RMI)
+ // See bug 4982668
+ args.remove("-expectedCreateException");
+ args.remove("-expectedGetException");
+ args.remove("-expectedSetException");
+ args.remove("-expectedInvokeException");
+ args.remove("-expectedConnectException");
+
+
+ // Here do connect to the JMX Server
+ String username = System.getProperty("username");
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::run: CONNECT on behalf of \"" + username + "\"");
+ doConnect(args, expectedConnectException);
+
+ // If the connection did not fail, perform some requests.
+ // At this stage the mbeanserver connection is up and running
+ if (mbsc != null) {
+ ObjectName on = new ObjectName("defaultDomain:class=Simple");
+
+ // Create request
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::run: CREATE on behalf of \"" +
+ username + "\"");
+ errorCount += doCreateRequest(mbsc,
+ new ObjectName("defaultDomain:class=Simple,user=" + username),
+ expectedCreateException);
+
+ // Get request
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::run: GET on behalf of \"" +
+ username + "\"");
+ errorCount += doGetRequest(mbsc, on, expectedGetException);
+
+ // Set request
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::run: SET on behalf of \"" +
+ username + "\"");
+ errorCount += doSetRequest(mbsc, on, expectedSetException);
+
+ // Invoke request
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::run: INVOKE on behalf of \"" +
+ username + "\"");
+ errorCount += doInvokeRequest(mbsc, on, expectedInvokeException);
+ }
+
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ } finally {
+ // Terminate the JMX Client
+ try {
+ cc.close();
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ }
+ }
+
+ System.out.println("ClientSide::run: Done") ;
+
+ // Handle result
+ if (errorCount == 0) {
+ System.out.println("ClientSide::run: (OK) authorization test succeeded.");
+ } else {
+ String message = "AuthorizationTest$ClientSide::run: (ERROR) " +
+ " authorization test failed with " +
+ errorCount + " error(s)";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+
+ protected void doConnect(Map<String, Object> args,
+ boolean expectedException) {
+
+ String msgTag = "ClientSide::doConnect";
+ boolean throwRuntimeException = false;
+ String message = "";
+
+ try {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doConnect: Connect the client");
+
+ // Collect connection environment
+ HashMap<String, Object> env = new HashMap<>();
+
+ Object value = args.get("-mapType");
+ if (value != null) {
+ String username = System.getProperty("username");
+ String password = System.getProperty("password");
+ Utils.debug(Utils.DEBUG_STANDARD,
+ msgTag + "add \"jmx.remote.credentials\" = \"" +
+ username + "\", \"" + password + "\"");
+ env.put("jmx.remote.credentials",
+ new String[] { username , password });
+ }
+
+ // Get a connection to remote mbean server
+ JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl"));
+ cc = JMXConnectorFactory.connect(addr,env);
+ mbsc = cc.getMBeanServerConnection();
+
+ if (expectedException) {
+ message = "ClientSide::doConnect: (ERROR) " +
+ "Connect did not fail with expected SecurityException";
+ System.out.println(message);
+ throwRuntimeException = true;
+ } else {
+ System.out.println("ClientSide::doConnect: (OK) Connect succeed");
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true);
+ if (expectedException) {
+ if (e instanceof java.lang.SecurityException) {
+ System.out.println("ClientSide::doConnect: (OK) " +
+ "Connect failed with expected SecurityException");
+ } else {
+ message = "ClientSide::doConnect: (ERROR) " +
+ "Create failed with " + e.getClass() +
+ " instead of expected SecurityException";
+ System.out.println(message);
+ throwRuntimeException = true;
+ }
+ } else {
+ message = "ClientSide::doConnect: (ERROR) " +
+ "Connect failed";
+ System.out.println(message);
+ throwRuntimeException = true;
+ }
+ }
+
+ // If the connection failed, or if the connection succeeded but should not,
+ // no need to go further => throw RuntimeException and exit the test
+ if (throwRuntimeException) {
+ throw new RuntimeException(message);
+ }
+ }
+
+ protected int doCreateRequest(MBeanServerConnection mbsc,
+ ObjectName on,
+ boolean expectedException) {
+ int errorCount = 0;
+
+ try {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doCreateRequest: Create and register the MBean") ;
+
+ mbsc.createMBean("Simple", on) ;
+
+ if (expectedException) {
+ System.out.println("ClientSide::doCreateRequest: " +
+ "(ERROR) Create did not fail with expected SecurityException");
+ errorCount++;
+ } else {
+ System.out.println("ClientSide::doCreateRequest: (OK) Create succeed") ;
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ if (expectedException) {
+ if (e instanceof java.lang.SecurityException) {
+ System.out.println("ClientSide::doCreateRequest: " +
+ "(OK) Create failed with expected SecurityException") ;
+ } else {
+ System.out.println("ClientSide::doCreateRequest: " +
+ "(ERROR) Create failed with " +
+ e.getClass() + " instead of expected SecurityException");
+ errorCount++;
+ }
+ } else {
+ System.out.println("ClientSide::doCreateRequest: " +
+ "(ERROR) Create failed");
+ errorCount++;
+ }
+ }
+ return errorCount;
+ }
+
+ protected int doGetRequest(MBeanServerConnection mbsc,
+ ObjectName on,
+ boolean expectedException) {
+ int errorCount = 0;
+
+ try {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doGetRequest: Get attributes of the MBean") ;
+
+ mbsc.getAttribute(on, "Attribute");
+
+ if (expectedException) {
+ System.out.println("ClientSide::doGetRequest: " +
+ "(ERROR) Get did not fail with expected SecurityException");
+ errorCount++;
+ } else {
+ System.out.println("ClientSide::doGetRequest: (OK) Get succeed") ;
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ if (expectedException) {
+ if (e instanceof java.lang.SecurityException) {
+ System.out.println("ClientSide::doGetRequest: " +
+ "(OK) Get failed with expected SecurityException") ;
+ } else {
+ System.out.println("ClientSide::doGetRequest: " +
+ "(ERROR) Get failed with " +
+ e.getClass() + " instead of expected SecurityException");
+ errorCount++;
+ }
+ } else {
+ System.out.println("ClientSide::doGetRequest: (ERROR) Get failed");
+ errorCount++;
+ }
+ }
+
+ return errorCount;
+ }
+
+ protected int doSetRequest(MBeanServerConnection mbsc,
+ ObjectName on,
+ boolean expectedException) {
+ int errorCount = 0;
+
+ try {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doSetRequest: Set attributes of the MBean") ;
+
+ Attribute attribute = new Attribute("Attribute", "My value") ;
+ mbsc.setAttribute(on, attribute) ;
+
+ if (expectedException) {
+ System.out.println("ClientSide::doSetRequest: " +
+ "(ERROR) Set did not fail with expected SecurityException");
+ errorCount++;
+ } else {
+ System.out.println("ClientSide::doSetRequest: (OK) Set succeed") ;
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ if (expectedException) {
+ if (e instanceof java.lang.SecurityException) {
+ System.out.println("ClientSide::doSetRequest: " +
+ "(OK) Set failed with expected SecurityException") ;
+ } else {
+ System.out.println("ClientSide::doSetRequest: " +
+ "(ERROR) Set failed with " +
+ e.getClass() + " instead of expected SecurityException");
+ errorCount++;
+ }
+ } else {
+ System.out.println("ClientSide::doSetRequest: (ERROR) Set failed");
+ errorCount++;
+ }
+ }
+ return errorCount;
+ }
+
+ protected int doInvokeRequest(MBeanServerConnection mbsc,
+ ObjectName on,
+ boolean expectedException) {
+ int errorCount = 0;
+
+ try {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doInvokeRequest: Invoke operations on the MBean") ;
+
+ mbsc.invoke(on, "operation", null, null) ;
+
+ if (expectedException) {
+ System.out.println("ClientSide::doInvokeRequest: " +
+ "(ERROR) Invoke did not fail with expected SecurityException");
+ errorCount++;
+ } else {
+ System.out.println("ClientSide::doInvokeRequest: (OK) Invoke succeed") ;
+ }
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ if (expectedException) {
+ if (e instanceof java.lang.SecurityException) {
+ System.out.println("ClientSide::doInvokeRequest: " +
+ "(OK) Invoke failed with expected SecurityException") ;
+ } else {
+ System.out.println("ClientSide::doInvokeRequest: " +
+ " (ERROR) Invoke failed with " +
+ e.getClass() + " instead of expected SecurityException");
+ errorCount++;
+ }
+ } else {
+ System.out.println("ClientSide::doInvokeRequest: " +
+ "(ERROR) Invoke failed");
+ errorCount++;
+ }
+ }
+ return errorCount;
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/MBS_Light.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2003, 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.security.AccessControlContext;
+import java.security.AccessController;
+import javax.security.auth.Subject;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.management.MBeanRegistration ;
+import javax.management.MBeanServer ;
+import javax.management.ObjectName ;
+import javax.management.NotificationBroadcasterSupport;
+import javax.management.NotificationListener;
+import javax.management.Notification;
+
+public class MBS_Light extends NotificationBroadcasterSupport
+ implements MBS_LightMBean, MBeanRegistration, NotificationListener
+{
+ private RjmxMBeanParameter param = null ;
+ private String aString = "notset" ;
+ private int anInt = 0 ;
+ private MBeanServer mbs = null ;
+ private ObjectName objname = null ;
+ private Exception anException = null ;
+ private Error anError = null ;
+ private int count = 0;
+ private SimpleListener listener = new SimpleListener();
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR MBS_Light")
+ public MBS_Light() {
+ }
+
+ @SqeDescriptorKey("ONE RjmxMBeanParameter PARAMETER CONSTRUCTOR MBS_Light")
+ public MBS_Light(@SqeDescriptorKey("CONSTRUCTOR PARAMETER param")
+ RjmxMBeanParameter param) {
+ this.param = param ;
+ }
+
+ @SqeDescriptorKey("ONE String PARAMETER CONSTRUCTOR MBS_Light")
+ public MBS_Light(@SqeDescriptorKey("CONSTRUCTOR PARAMETER param")String param) {
+ this.aString = param ;
+ }
+
+ // Getter for property param
+ public RjmxMBeanParameter getParam() {
+ return this.param ;
+ }
+
+ // Setter for property param
+ public void setParam(RjmxMBeanParameter param) {
+ this.param = param ;
+ }
+
+ // Getter for property aString
+ public String getAstring() {
+ return this.aString ;
+ }
+
+ // Setter for property aString
+ public void setAstring(String aString) {
+ this.aString = aString ;
+ }
+
+ // Getter for property anInt
+ public int getAnInt() {
+ return this.anInt ;
+ }
+
+ // Setter for property anInt
+ public void setAnInt(int anInt) {
+ this.anInt = anInt ;
+ }
+
+ // Getter for property anException
+ public Exception getAnException() {
+ return this.anException ;
+ }
+
+ // Setter for property anException
+ public void setAnException(Exception anException) {
+ this.anException = anException ;
+ }
+
+ // Getter for property anError
+ public Error getAnError() {
+ return this.anError ;
+ }
+
+ // Setter for property anError
+ public void setAnError(Error anError) {
+ this.anError = anError ;
+ }
+
+ // An operation
+ public RjmxMBeanParameter operate1(String name) {
+ return new RjmxMBeanParameter(name) ;
+ }
+
+ // An operation
+ public String operate2(RjmxMBeanParameter param) {
+ return param.name ;
+ }
+
+ // An operation
+ public void throwError() {
+ throw new Error("JSR-160-ERROR");
+ }
+
+ // An operation
+ public void throwException() throws Exception {
+ throw new Exception("JSR-160-EXCEPTION");
+ }
+
+ // MBeanRegistration method
+ public void postDeregister() {
+ }
+
+ // MBeanRegistration method
+ public void postRegister(Boolean registrationDone) {
+ }
+
+ // MBeanRegistration method
+ public void preDeregister()
+ throws Exception
+ {
+ }
+
+ // MBeanRegistration method
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception
+ {
+ this.mbs = server ;
+ if ( name == null ) {
+ this.objname = new ObjectName("protocol:class=MBS_Light") ;
+ }
+ else {
+ this.objname = name ;
+ }
+ return this.objname ;
+ }
+
+ public synchronized void handleNotification(Notification notification,
+ Object handback) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "MBS_Light::handleNotification: " + notification);
+ listener.handleNotification(notification, handback);
+ }
+
+ // Send a notification
+ public void sendNotification() {
+ Notification notification =
+ new Notification("JSR160-TCK-NOTIFICATION", this, count++);
+ sendNotification(notification);
+ }
+
+ public Object waitForNotificationHB() {
+ return listener.waitForNotificationHB();
+ }
+
+ // Receive multi notifications and send back handbacks
+ public synchronized Object[] waitForMultiNotifications(String nb) {
+ return listener.waitForMultiNotifications(Integer.valueOf(nb).intValue());
+ }
+
+ // Receive a notification
+ public synchronized String waitForNotification() {
+ return listener.waitForNotification();
+ }
+
+ // Is the notification received
+ public synchronized Boolean notificationReceived() {
+ return Boolean.valueOf(listener.isNotificationReceived());
+ }
+
+ // The authorization Id
+ public String getAuthorizationId() {
+ AccessControlContext acc = AccessController.getContext();
+ Subject subject = Subject.getSubject(acc);
+ Set<Principal> principals = subject.getPrincipals();
+ Iterator<Principal> i = principals.iterator();
+ StringBuffer buffer = new StringBuffer();
+ while(i.hasNext()) {
+ Principal p = i.next();
+ buffer.append(p.getName());
+ if(i.hasNext())
+ buffer.append(" ");
+ }
+
+ return buffer.toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/MBS_LightMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2003, 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.
+ */
+
+@SqeDescriptorKey("INTERFACE MBS_LightMBean")
+public interface MBS_LightMBean {
+ // Getter for property param
+ @SqeDescriptorKey("ATTRIBUTE Param")
+ public RjmxMBeanParameter getParam() ;
+
+ // Setter for property param
+ @SqeDescriptorKey("ATTRIBUTE Param")
+ public void setParam(RjmxMBeanParameter param) ;
+
+ // Getter for property aString
+ @SqeDescriptorKey("ATTRIBUTE Astring")
+ public String getAstring() ;
+
+ // Setter for property aString
+ @SqeDescriptorKey("ATTRIBUTE Astring")
+ public void setAstring(String aString) ;
+
+ // Getter for property anInt
+ @SqeDescriptorKey("ATTRIBUTE AnInt")
+ public int getAnInt() ;
+
+ // Setter for property anInt
+ @SqeDescriptorKey("ATTRIBUTE AnInt")
+ public void setAnInt(int anInt) ;
+
+ // Getter for property anException
+ @SqeDescriptorKey("ATTRIBUTE AnException")
+ public Exception getAnException() ;
+
+ // Setter for property anException
+ @SqeDescriptorKey("ATTRIBUTE AnException")
+ public void setAnException(Exception anException) ;
+
+ // Getter for property anError
+ @SqeDescriptorKey("ATTRIBUTE AnError")
+ public Error getAnError() ;
+
+ // Setter for property anError
+ @SqeDescriptorKey("ATTRIBUTE AnError")
+ public void setAnError(Error anError) ;
+
+ // An operation
+ @SqeDescriptorKey("OPERATION operate1")
+ public RjmxMBeanParameter operate1(
+ @SqeDescriptorKey("OPERATION PARAMETER name")String name) ;
+
+ // An operation
+ @SqeDescriptorKey("OPERATION operate2")
+ public String operate2(
+ @SqeDescriptorKey("OPERATION PARAMETER param")RjmxMBeanParameter param) ;
+
+ // Throws an error
+ @SqeDescriptorKey("OPERATION throwError")
+ public void throwError();
+
+ // Throws an exception
+ @SqeDescriptorKey("OPERATION throwException")
+ public void throwException() throws Exception;
+
+ // Send a notification
+ @SqeDescriptorKey("OPERATION sendNotification")
+ public void sendNotification();
+
+ // Receive a notification and return the type
+ @SqeDescriptorKey("OPERATION waitForNotification")
+ public String waitForNotification();
+
+ // Receive a notification and return the HandBack
+ @SqeDescriptorKey("OPERATION waitForNotificationHB")
+ public Object waitForNotificationHB();
+
+ // Receive multi notifications and return the HandBacks
+ @SqeDescriptorKey("OPERATION waitForMultiNotifications")
+ public Object[] waitForMultiNotifications(
+ @SqeDescriptorKey("OPERATION PARAMETER nb")String nb);
+
+ // Is the notification received
+ @SqeDescriptorKey("OPERATION notificationReceived")
+ public Boolean notificationReceived();
+
+ // Return the current authorization Id
+ @SqeDescriptorKey("OPERATION getAuthorizationId")
+ public String getAuthorizationId();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/RjmxMBeanParameter.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003, 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.io.Serializable ;
+
+/**
+ * That class is used to modelize a parameter to be used as MBean property
+ * value or MBean operation parameter or returned value.
+ */
+public class RjmxMBeanParameter implements Serializable {
+ public String name = "unset" ;
+
+ public RjmxMBeanParameter() {
+ }
+
+ public RjmxMBeanParameter(String name) {
+ this.name = name ;
+ }
+
+ public boolean equals(Object obj) {
+ if ( this.name.equals(((RjmxMBeanParameter)obj).name) ) {
+ return true ;
+ } else {
+ return false ;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/SecurityTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2003, 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.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks various secure ways of connecting from remote jmx client
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile MBS_Light.java ServerDelegate.java TestSampleLoginModule.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=UNKNOWN_username -Dpassword=SQE_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=SQE_username -Dpassword=WRONG_password SecurityTest -server -mapType x.password.file -client -mapType credentials -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=TestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dsusername=TestJMXAuthenticatorUsername -Dspassword=TestJMXAuthenticatorPassword -Dusername=AnotherTestJMXAuthenticatorUsername -Dpassword=TestJMXAuthenticatorPassword SecurityTest -server -mapType x.authenticator -client -mapType credentials -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentials
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config.UNKNOWN -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.PasswordFileAuthentication -client -mapType credentialss -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dpassword.file=password.properties -Dusername=usernameFileLoginModule -Dpassword=passwordFileLoginModule SecurityTest -server -mapType x.login.config.UnknownAuthentication -client -mapType credentials -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=usernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dlogin.config.file=${test.src}/login.config -Dsusername=usernameSampleLoginModule -Dspassword=passwordSampleLoginModule -Dpassword.file=password.properties -Dusername=AnotherUsernameSampleLoginModule -Dpassword=passwordSampleLoginModule SecurityTest -server -mapType x.login.config.SampleLoginModule -client -mapType credentials -expectedThrowable java.lang.SecurityException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword WRONG_password -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl -keystore keystoreAgent -keystorepassword glopglop -client -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -keystore keystoreClient -keystorepassword WRONG_password -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -truststore truststoreAgent -truststorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.need.client.authentication -keystore keystoreAgent -keystorepassword glopglop -client -keystore keystoreClient -keystorepassword glopglop -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_SHA SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.md5 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.cipher.suites.sha -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=TLSv1 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.sslv3 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD -Djavax.rmi.ssl.client.enabledProtocols=SSLv3 SecurityTest -server -mapType rmi.client.socket.factory.ssl;rmi.server.socket.factory.ssl.enabled.protocols.tlsv1 -keystore keystoreAgent -keystorepassword glopglop -client -truststore truststoreClient -truststorepassword glopglop -expectedThrowable java.io.IOException
+ */
+
+import java.io.File;
+import java.util.Map ;
+import java.util.HashMap ;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory ;
+import javax.management.MBeanServerConnection;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.Attribute ;
+import javax.management.ObjectName ;
+
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+import java.security.Security;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.JDKToolFinder;
+
+public class SecurityTest {
+
+ static final String SERVER_CLASS_NAME = "SecurityTest";
+ static final String CLIENT_CLASS_NAME = "SecurityTest$ClientSide";
+ static final String CLIENT_CLASS_MAIN = CLIENT_CLASS_NAME;
+
+ static final String USERNAME_PROPERTY = "username";
+ static final String PASSWORD_PROPERTY = "password";
+
+ static final String SERVER_DELEGATE_MBEAN_NAME =
+ "defaultDomain:class=ServerDelegate";
+
+ static final String RMI_SERVER_SOCKET_FACTORY_SSL = "rmi.server.socket.factory.ssl";
+ static final String RMI_CLIENT_SOCKET_FACTORY_SSL = "rmi.client.socket.factory.ssl";
+ static final String KEYSTORE_PROPNAME = "javax.net.ssl.keyStore";
+ static final String KEYSTORE_PWD_PROPNAME = "javax.net.ssl.keyStorePassword";
+ static final String TRUSTSTORE_PROPNAME = "javax.net.ssl.trustStore";
+ static final String TRUSTSTORE_PWD_PROPNAME = "javax.net.ssl.trustStorePassword";
+
+ static final String RMI_SSL_CLIENT_ENABLEDCIPHERSUITES =
+ "javax.rmi.ssl.client.enabledCipherSuites";
+ static final String RMI_SSL_CLIENT_ENABLEDPROTOCOLS =
+ "javax.rmi.ssl.client.enabledProtocols";
+
+ private JMXConnectorServer cs;
+
+ // Construct and set keyStore properties from given map
+ static void setKeyStoreProperties(Map<String, Object> map) {
+
+ String keyStore = (String) map.get("-keystore");
+ keyStore = buildSourcePath(keyStore);
+ System.setProperty(KEYSTORE_PROPNAME, keyStore);
+ System.out.println("keyStore location = \"" + keyStore + "\"");
+
+ String password = (String) map.get("-keystorepassword");
+ System.setProperty(KEYSTORE_PWD_PROPNAME, password);
+ System.out.println("keyStore password = " + password);
+
+ }
+
+ // Construct and set trustStore properties from given map
+ static void setTrustStoreProperties(Map<String, Object> map) {
+
+ String trustStore = (String) map.get("-truststore");
+ trustStore = buildSourcePath(trustStore);
+ System.setProperty(TRUSTSTORE_PROPNAME, trustStore);
+ System.out.println("trustStore location = \"" + trustStore + "\"");
+
+ String password = (String) map.get("-truststorepassword");
+ System.setProperty(TRUSTSTORE_PWD_PROPNAME, password);
+ System.out.println("trustStore password = " + password);
+
+ }
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+
+ // Supported parameters list format is :
+ // "MainClass [-server <param-spec> ...] [-client <param-spec> ...]
+ // with <param-spec> either "-parami valuei" or "-parami"
+ HashMap<String, Object> serverMap = new HashMap<>() ;
+ int clientArgsIndex =
+ Utils.parseServerParameters(args, SERVER_CLASS_NAME, serverMap);
+
+ // Extract and records client params
+ String[] clientParams = null;
+ if (clientArgsIndex < args.length) {
+ int clientParamsSize = args.length - clientArgsIndex;
+ clientParams = new String[clientParamsSize];
+ System.arraycopy(args, clientArgsIndex, clientParams, 0, clientParamsSize);
+ } else {
+ clientParams = new String[0];
+ }
+
+ // Run test
+ SecurityTest test = new SecurityTest();
+ test.run(serverMap, clientParams);
+
+ }
+
+ // Return full path of filename in the test sopurce directory
+ private static String buildSourcePath(String filename) {
+ return System.getProperty("test.src") + File.separator + filename;
+ }
+
+ /*
+ * Collects security run params for server side.
+ */
+ private HashMap<String, Object> setServerSecurityEnv(Map<String, Object> map)
+ throws Exception {
+
+ // Creates Authentication environment from server side params
+ HashMap<String, Object> env = new HashMap<>();
+
+ // Retrieve and set keystore and truststore config if any
+ if (map.containsKey("-keystore") &&
+ map.get("-keystore") != null) {
+ setKeyStoreProperties(map);
+ }
+ System.out.println("Done keystore properties");
+
+ if (map.containsKey("-truststore") &&
+ map.get("-truststore") != null) {
+ setTrustStoreProperties(map);
+ }
+ System.out.println("Done truststore properties");
+
+ String value = null;
+ if ((value = (String)map.get("-mapType")) != null) {
+
+ // Case of remote password file with all authorized credentials
+ if (value.contains("x.password.file")) {
+ String passwordFileStr = buildSourcePath("password.properties");
+ env.put("jmx.remote.x.password.file", passwordFileStr);
+ System.out.println("Added " + passwordFileStr +
+ " file as jmx.remote.x.password.file");
+ }
+
+ // Case of dedicated authenticator class : TestJMXAuthenticator
+ if (value.contains("x.authenticator")) {
+ env.put("jmx.remote.authenticator", new TestJMXAuthenticator()) ;
+ System.out.println(
+ "Added \"jmx.remote.authenticator\" = TestJMXAuthenticator");
+ }
+
+ // Case of security config file with standard Authentication
+ if (value.contains("x.login.config.PasswordFileAuthentication")) {
+ String loginConfig = System.getProperty("login.config.file");
+
+ // Override the default JAAS configuration
+ System.setProperty("java.security.auth.login.config",
+ "file:" + loginConfig);
+ System.out.println("Overrided default JAAS configuration with " +
+ "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ;
+
+ env.put("jmx.remote.x.login.config", "PasswordFileAuthentication") ;
+ System.out.println(
+ "Added \"jmx.remote.x.login.config\" = " +
+ "\"PasswordFileAuthentication\"") ;
+
+ // redirects "password.file" property to file in ${test.src}
+ String passwordFileStr =
+ buildSourcePath(System.getProperty("password.file"));
+ System.setProperty("password.file", passwordFileStr);
+ System.out.println(
+ "Redirected \"password.file\" property value to = " +
+ passwordFileStr) ;
+ }
+
+ // Case of security config file with unexisting athentication config
+ if (value.contains("x.login.config.UnknownAuthentication")) {
+ String loginConfig = System.getProperty("login.config.file");
+
+ // Override the default JAAS configuration
+ System.setProperty("java.security.auth.login.config",
+ "file:" + loginConfig);
+ System.out.println("Overrided default JAAS configuration with " +
+ "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ;
+
+ env.put("jmx.remote.x.login.config", "UnknownAuthentication") ;
+ System.out.println(
+ "Added \"jmx.remote.x.login.config\" = " +
+ "\"UnknownAuthentication\"") ;
+
+ // redirects "password.file" property to file in ${test.src}
+ String passwordFileStr =
+ buildSourcePath(System.getProperty("password.file"));
+ System.setProperty("password.file", passwordFileStr);
+ System.out.println(
+ "Redirected \"password.file\" property value to = " +
+ passwordFileStr) ;
+ }
+
+ // Case of security config file with dedicated login module
+ if (value.contains("x.login.config.SampleLoginModule")) {
+ String loginConfig = System.getProperty("login.config.file");
+
+ // Override the default JAAS configuration
+ System.setProperty("java.security.auth.login.config",
+ "file:" + loginConfig);
+ System.out.println("Overrided default JAAS configuration with " +
+ "\"java.security.auth.login.config\" = \"" + loginConfig + "\"") ;
+
+ env.put("jmx.remote.x.login.config", "SampleLoginModule") ;
+ System.out.println(
+ "Added \"jmx.remote.x.login.config\" = " +
+ "\"SampleLoginModule\"") ;
+ }
+
+ // Simple rmi ssl authentication
+ if (value.contains(RMI_CLIENT_SOCKET_FACTORY_SSL)) {
+ env.put("jmx.remote.rmi.client.socket.factory",
+ new SslRMIClientSocketFactory()) ;
+ System.out.println(
+ "Added \"jmx.remote.rmi.client.socket.factory\"" +
+ " = SslRMIClientSocketFactory") ;
+ }
+
+ if (value.contains(RMI_SERVER_SOCKET_FACTORY_SSL)) {
+ if (value.contains(
+ "rmi.server.socket.factory.ssl.need.client.authentication")) {
+ // rmi ssl authentication with client authentication
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory(null, null, true)) ;
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory with client authentication") ;
+
+ } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.md5")) {
+ // Allows all ciphering and protocols for testing purpose
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory(
+ new String[] {"SSL_RSA_WITH_RC4_128_MD5"}, null, false));
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_MD5 cipher suite");
+
+ } else if (value.contains("rmi.server.socket.factory.ssl.enabled.cipher.suites.sha")) {
+ // Allows all ciphering and protocols for testing purpose
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory(
+ new String[] { "SSL_RSA_WITH_RC4_128_SHA" }, null, false)) ;
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory with SSL_RSA_WITH_RC4_128_SHA cipher suite") ;
+
+ } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.sslv3")) {
+ // Allows all ciphering and protocols for testing purpose
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory(null, new String[] {"SSLv3"}, false)) ;
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory with SSLv3 protocol") ;
+
+ } else if (value.contains("rmi.server.socket.factory.ssl.enabled.protocols.tlsv1")) {
+ // Allows all ciphering and protocols for testing purpose
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory(null, new String[] {"TLSv1"}, false)) ;
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory with TLSv1 protocol") ;
+
+ } else {
+ env.put("jmx.remote.rmi.server.socket.factory",
+ new SslRMIServerSocketFactory());
+ System.out.println(
+ "Added \"jmx.remote.rmi.server.socket.factory\"" +
+ " = SslRMIServerSocketFactory");
+ }
+ }
+ }
+
+ return env;
+ }
+
+ /*
+ * Create the MBeansServer side of the test and returns its address
+ */
+ private JMXServiceURL createServerSide(Map<String, Object> serverMap)
+ throws Exception {
+ final int NINETY_SECONDS = 90;
+
+ System.out.println("SecurityTest::createServerSide: Start") ;
+
+ // Prepare server side security env
+ HashMap<String, Object> env = setServerSecurityEnv(serverMap);
+
+ // Create and start mbean server and connector server
+ MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ cs = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
+ cs.start();
+
+ // Waits availibility of connector server
+ Utils.waitReady(cs, NINETY_SECONDS);
+
+ JMXServiceURL addr = cs.getAddress();
+
+ System.out.println("SecurityTest::createServerSide: Done.") ;
+
+ return addr;
+ }
+
+ /*
+ * Creating command-line for running subprocess JVM:
+ *
+ * JVM command line is like:
+ * {test_jdk}/bin/java {defaultopts} -cp {test.class.path} {testopts} main
+ *
+ * {defaultopts} are the default java options set by the framework.
+ *
+ */
+ private List<String> buildCommandLine(String args[]) {
+
+ System.out.println("SecurityTest::buildCommandLine: Start") ;
+
+ List<String> opts = new ArrayList<>();
+ opts.add(JDKToolFinder.getJDKTool("java"));
+ opts.addAll(Arrays.asList(jdk.testlibrary.Utils.getTestJavaOpts()));
+
+ // We need to forward some properties to the client side
+ opts.add("-Dtest.src=" + System.getProperty("test.src"));
+
+ String usernameValue = System.getProperty(USERNAME_PROPERTY);
+ if (usernameValue != null) {
+ System.out.println("SecurityTest::buildCommandLine: "+
+ " forward username property to client side");
+ opts.add("-D" + USERNAME_PROPERTY + "=" + usernameValue);
+ }
+ String passwordValue = System.getProperty(PASSWORD_PROPERTY);
+ if (passwordValue != null) {
+ System.out.println("SecurityTest::buildCommandLine: "+
+ " forward password property to client side");
+ opts.add("-D" + PASSWORD_PROPERTY + "=" + passwordValue);
+ }
+
+ String enabledCipherSuites =
+ System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES);
+ if (enabledCipherSuites != null) {
+ System.out.println("SecurityTest::buildCommandLine: "+
+ " forward enabledCipherSuites property to client side");
+ opts.add("-D" + RMI_SSL_CLIENT_ENABLEDCIPHERSUITES +
+ "=" + enabledCipherSuites);
+ }
+
+ String enabledProtocols =
+ System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS);
+ if (enabledProtocols != null) {
+ System.out.println("SecurityTest::buildCommandLine: "+
+ " forward enabledProtocols property to client side");
+ opts.add("-D" + RMI_SSL_CLIENT_ENABLEDPROTOCOLS +
+ "=" + enabledProtocols);
+ }
+
+ opts.add("-cp");
+ opts.add(System.getProperty("test.class.path", "test.class.path"));
+ opts.add(CLIENT_CLASS_MAIN);
+ opts.addAll(Arrays.asList(args));
+
+ System.out.println("SecurityTest::buildCommandLine: Done.") ;
+
+ return opts;
+ }
+
+ /**
+ * Runs SecurityTest$ClientSide with the passed options and redirects
+ * subprocess standard I/O to the current (parent) process. This provides a
+ * trace of what happens in the subprocess while it is runnning (and before
+ * it terminates).
+ *
+ * @param serviceUrlStr string representing the JMX service Url to connect to.
+ */
+ private int runClientSide(String args[], String serviceUrlStr) throws Exception {
+
+ System.out.println("SecurityTest::runClientSide: Start") ;
+
+ // Building command-line
+ List<String> opts = buildCommandLine(args);
+ opts.add("-serviceUrl");
+ opts.add(serviceUrlStr);
+
+ // Launch separate JVM subprocess
+ int exitCode = 0;
+ String[] optsArray = opts.toArray(new String[0]);
+ ProcessBuilder pb = new ProcessBuilder(optsArray);
+ Process p = ProcessTools.startProcess("SecurityTest$ClientSide", pb);
+
+ // Handling end of subprocess
+ try {
+ exitCode = p.waitFor();
+ if (exitCode != 0) {
+ System.out.println(
+ "Subprocess unexpected exit value of [" + exitCode +
+ "]. Expected 0.\n");
+ }
+ } catch (InterruptedException e) {
+ System.out.println("Parent process interrupted with exception : \n " + e + " :" );
+
+ // Parent thread unknown state, killing subprocess.
+ p.destroyForcibly();
+
+ throw new RuntimeException(
+ "Parent process interrupted with exception : \n " + e + " :" );
+
+ } finally {
+ if (p.isAlive()) {
+ p.destroyForcibly();
+ }
+
+ System.out.println("SecurityTest::runClientSide: Done") ;
+
+ return exitCode;
+ }
+
+ }
+
+ public void run(Map<String, Object> serverArgs, String clientArgs[]) {
+
+ System.out.println("SecurityTest::run: Start") ;
+ int errorCount = 0;
+
+ try {
+ // Initialise the server side
+ JMXServiceURL urlToUse = createServerSide(serverArgs);
+
+ // Run client side
+ errorCount = runClientSide(clientArgs, urlToUse.toString());
+
+ if ( errorCount == 0 ) {
+ System.out.println("SecurityTest::run: Done without any error") ;
+ } else {
+ System.out.println(
+ "SecurityTest::run: Done with " + errorCount + " error(s)");
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+
+ cs.stop();
+
+ } catch(Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private static class ClientSide {
+
+ private JMXConnector cc = null;
+ private MBeanServerConnection mbsc = null;
+
+ public static void main(String args[]) throws Exception {
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+
+ // Supported parameters list format is : "MainClass [-client <param-spec> ...]
+ // with <param-spec> either "-parami valuei" or "-parami"
+ HashMap<String, Object> clientMap = new HashMap<>() ;
+ Utils.parseClientParameters(args, CLIENT_CLASS_NAME, clientMap);
+
+ // Run test
+ ClientSide test = new ClientSide();
+ test.run(clientMap);
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("ClientSide::run: Start");
+ int errorCount = 0;
+
+ try {
+ // Setup client side parameters
+ HashMap<String, Object> env = new HashMap<>();
+
+ // If needed allows all ciphering and protocols for testing purpose
+ if (System.getProperty(RMI_SSL_CLIENT_ENABLEDCIPHERSUITES) != null) {
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+ }
+
+ // If needed allows all ciphering and protocols for testing purpose
+ if (System.getProperty(RMI_SSL_CLIENT_ENABLEDPROTOCOLS) != null) {
+ Security.setProperty("jdk.tls.disabledAlgorithms", "");
+ }
+
+ // Retrieve and set keystore and truststore config if any
+ if (args.containsKey("-keystore") &&
+ args.get("-keystore") != null) {
+ SecurityTest.setKeyStoreProperties(args);
+ }
+ if (args.containsKey("-truststore") &&
+ args.get("-truststore") != null) {
+ SecurityTest.setTrustStoreProperties(args);
+ }
+
+ Object value = args.get("-mapType");
+ if ((value != null) &&
+ value.equals("credentials")) {
+ String username = System.getProperty("username");
+ String password = System.getProperty("password");
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "add \"jmx.remote.credentials\" = \"" +
+ username + "\", \"" + password + "\"");
+ env.put("jmx.remote.credentials",
+ new String[] { username , password });
+ }
+
+ String expectedThrowable = (String) args.get("-expectedThrowable");
+
+ String authCallCountName = "-expectedAuthenticatorCallCount";
+ int authCallCountValue = 0;
+ if (args.containsKey(authCallCountName)) {
+ authCallCountValue =
+ (new Integer((String) args.get(authCallCountName))).intValue();
+ }
+
+ try {
+ // Get a connection to remote mbean server
+ JMXServiceURL addr = new JMXServiceURL((String)args.get("-serviceUrl"));
+ cc = JMXConnectorFactory.connect(addr,env);
+ mbsc = cc.getMBeanServerConnection();
+
+ // In case we should have got an exception
+ if (expectedThrowable != null) {
+ System.out.println("ClientSide::run: (ERROR) " +
+ " Connect did not fail with expected " + expectedThrowable);
+ errorCount++;
+ } else {
+ System.out.println("ClientSide::run: (OK) Connect succeed");
+ }
+ } catch (Throwable e) {
+ Utils.printThrowable(e, true);
+ if (expectedThrowable != null) {
+ if (Utils.compareThrowable(e, expectedThrowable)) {
+ System.out.println("ClientSide::run: (OK) " +
+ "Connect failed with expected " + expectedThrowable);
+ } else {
+ System.out.println("ClientSide::run: (ERROR) Connect failed with " +
+ e.getClass() + " instead of expected " +
+ expectedThrowable);
+ errorCount++;
+ }
+ } else {
+ System.out.println("ClientSide::run: (ERROR) " +
+ "Connect failed with exception");
+ errorCount++;
+ }
+ }
+
+ // Depending on the client state,
+ // perform some requests
+ if (mbsc != null && errorCount == 0) {
+ // Perform some little JMX requests
+ System.out.println("ClientSide::run: Start sending requests");
+
+ doRequests();
+
+ // In case authentication has been used we check how it did.
+ if (authCallCountValue != 0) {
+ errorCount += checkAuthenticator(mbsc, authCallCountValue);
+ }
+ }
+ } catch (Exception e) {
+ Utils.printThrowable(e, true);
+ errorCount++;
+ } finally {
+ // Terminate the JMX Client if any
+ if (cc != null) {
+ try {
+ cc.close();
+ } catch (Exception e) {
+ Utils.printThrowable(e, true) ;
+ errorCount++;
+ }
+ }
+ }
+
+ System.out.println("ClientSide::run: Done");
+
+ // Handle result
+ if (errorCount != 0) {
+ throw new RuntimeException();
+ }
+ }
+
+ private void doRequests() throws Exception {
+
+ // Send some requests to the remote JMX server
+ ObjectName objName1 =
+ new ObjectName("TestDomain:class=MBS_Light,rank=1");
+ String mbeanClass = "MBS_Light";
+ Exception exception = new Exception("MY TEST EXCEPTION");
+ Attribute attException = new Attribute("AnException", exception);
+ Error error = new Error("MY TEST ERROR");
+ Attribute attError = new Attribute("AnError", error);
+ String opParamString = "TOTORO";
+ RjmxMBeanParameter opParam = new RjmxMBeanParameter(opParamString);
+ Object[] params1 = {opParamString};
+ String[] sig1 = {"java.lang.String"};
+ Object[] params2 = {opParam};
+ String[] sig2 = {"RjmxMBeanParameter"};
+
+ // Create and register the MBean
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doRequests: Create and register the MBean");
+ mbsc.createMBean(mbeanClass, objName1);
+ if (!mbsc.isRegistered(objName1)) {
+ throw new Exception("Unable to register an MBean");
+ }
+
+ // Set attributes of the MBean
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doRequests: Set attributes of the MBean");
+ mbsc.setAttribute(objName1, attException);
+ mbsc.setAttribute(objName1, attError);
+
+ // Get attributes of the MBean
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doRequests: Get attributes of the MBean");
+ Exception retException =
+ (Exception) mbsc.getAttribute(objName1,"AnException");
+ if (!retException.getMessage().equals(exception.getMessage())) {
+ System.out.println("Expected = " + exception);
+ System.out.println("Got = " + retException);
+ throw new Exception("Attribute AnException not as expected");
+ }
+ Error retError = (Error) mbsc.getAttribute(objName1, "AnError");
+ if (!retError.getMessage().equals(error.getMessage())) {
+ System.out.println("Expected = " + error);
+ System.out.println("Got = " + retError);
+ throw new Exception("Attribute AnError not as expected");
+ }
+
+ // Invoke operations on the MBean
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doRequests: Invoke operations on the MBean");
+ RjmxMBeanParameter res1 =
+ (RjmxMBeanParameter) mbsc.invoke(objName1, "operate1", params1, sig1);
+ if (!res1.equals(opParam)) {
+ System.out.println("Expected = " + opParam);
+ System.out.println("Got = " + res1);
+ throw new Exception("Operation operate1 behaved badly");
+ }
+ String res2 =
+ (String) mbsc.invoke(objName1, "operate2", params2, sig2);
+ if (!res2.equals(opParamString)) {
+ System.out.println("Expected = " + opParamString);
+ System.out.println("Got = " + res2);
+ throw new Exception("Operation operate2 behaved badly");
+ }
+
+ // Unregister the MBean
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "ClientSide::doRequests: Unregister the MBean");
+ mbsc.unregisterMBean(objName1);
+ if (mbsc.isRegistered(objName1)) {
+ throw new Exception("Unable to unregister an MBean");
+ }
+ }
+
+ /**
+ * Make some check about the instance of TestJMXAuthenticator.
+ * The authenticator is supposed to have set some properties on
+ * a ServerDelegate MBean.
+ * We compare the number of times it has been called with the expected value.
+ * We also check the Principal that has been given to the authenticator
+ * was not null.
+ * That method is of use to authentication with the JSR 262.
+ * @param mbs
+ * @param expectedAuthenticatorCallCount
+ * @return The number of errors encountered.
+ * @throws java.lang.Exception
+ */
+ protected int checkAuthenticator(MBeanServerConnection mbs,
+ int expectedAuthenticatorCallCount) throws Exception {
+ int errorCount = 0;
+
+ // Ensure the authenticator has been called the right number
+ // of times.
+ int callCount =
+ ((Integer) mbs.getAttribute(
+ new ObjectName(SERVER_DELEGATE_MBEAN_NAME),
+ "TestJMXAuthenticatorCallCount")).intValue();
+
+ if (callCount == expectedAuthenticatorCallCount) {
+ System.out.println("---- OK Authenticator has been called "
+ + expectedAuthenticatorCallCount + " time");
+ } else {
+ errorCount++;
+ System.out.println("---- ERROR Authenticator has been called " + callCount
+ + " times in place of " + expectedAuthenticatorCallCount);
+ }
+
+ // Ensure the provider has been called with
+ // a non null Principal.
+ String principalString =
+ (String) mbs.getAttribute(
+ new ObjectName(SERVER_DELEGATE_MBEAN_NAME),
+ "TestJMXAuthenticatorPrincipalString");
+
+ if (principalString == null) {
+ errorCount++;
+ System.out.println("---- ERROR Authenticator has been called"
+ + " with a null Principal");
+ } else {
+ if (principalString.length() > 0) {
+ System.out.println("---- OK Authenticator has been called"
+ + " with the Principal " + principalString);
+ } else {
+ errorCount++;
+ System.out.println("---- ERROR Authenticator has been called"
+ + " with an empty Principal");
+ }
+ }
+
+ return errorCount;
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/ServerDelegate.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2004, 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.security.Principal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.remote.JMXServiceURL ;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.StandardMBean;
+
+/**
+ * This class defines an MBean that can be registered and used on client side
+ * to handle informations or properties of the remote server.
+ *
+ * For example, this MBean can store IOR addresses
+ * of RMI/IIOP connector(s) used in a test.
+ *
+ * That MBean might not be used for testing purpose itself.
+ */
+public class ServerDelegate implements ServerDelegateMBean, MBeanRegistration {
+
+ private MBeanServer mbeanServer = null;
+ private List<JMXServiceURL> addresses = null;
+ private String port;
+ private static String javaVersion = System.getProperty("java.version");
+ private int sqeJmxwsCredentialsProviderCallCount = 0;
+ private String jmxwsCredentialsProviderUrl = null;
+ private int testJMXAuthenticatorCallCount = 0;
+ private Principal testJMXAuthenticatorPrincipal = null;
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR ServerDelegate")
+ public ServerDelegate() {
+ addresses = new ArrayList<JMXServiceURL>();
+ }
+
+ public ObjectName preRegister(MBeanServer server, ObjectName name)
+ throws Exception {
+ // Initialize MBeanServer attribute
+ mbeanServer = server;
+ return name;
+ }
+ public void postRegister(Boolean registrationDone) {
+ }
+ public void preDeregister() throws Exception {
+ }
+ public void postDeregister() {
+ }
+
+ public void addAddress(JMXServiceURL url) {
+ addresses.add(url) ;
+ }
+
+ public List<JMXServiceURL> getAddresses() {
+ return addresses ;
+ }
+
+ public void setPort(String p) {
+ port = p ;
+ }
+
+ public String getPort() {
+ return port ;
+ }
+
+ public String getJavaVersion() {
+ return javaVersion;
+ }
+
+ public void sqeJmxwsCredentialsProviderCalled() {
+ sqeJmxwsCredentialsProviderCallCount++;
+ }
+
+ public int getSqeJmxwsCredentialsProviderCallCount() {
+ return sqeJmxwsCredentialsProviderCallCount;
+ }
+
+ public void setJmxwsCredentialsProviderUrl(String url) {
+ jmxwsCredentialsProviderUrl = url;
+ }
+
+ public String getJmxwsCredentialsProviderUrl() {
+ return jmxwsCredentialsProviderUrl;
+ }
+
+ public void testJMXAuthenticatorCalled() {
+ testJMXAuthenticatorCallCount++;
+ }
+
+ public int getTestJMXAuthenticatorCallCount() {
+ return testJMXAuthenticatorCallCount;
+ }
+
+ public void setTestJMXAuthenticatorPrincipal(Principal principal) {
+ testJMXAuthenticatorPrincipal = principal;
+ }
+
+ public String getTestJMXAuthenticatorPrincipalString() {
+ if ( testJMXAuthenticatorPrincipal != null ) {
+ return testJMXAuthenticatorPrincipal.toString();
+ }
+
+ return null;
+ }
+
+ /**
+ * Instantiates and registers a StandardMBean in the MBean server.
+ *
+ * @param implementationClassName
+ * The implementation class name of the MBean.
+ * @param interfaceClassName
+ * The management interface class name of the MBean.
+ * @param isMXBean
+ * If true, the resultant MBean is an MXBean.
+ * @param name
+ * The object name of the StandardMBean.
+ */
+ @SuppressWarnings("unchecked")
+ public void createStandardMBean(
+ String implementationClassName,
+ String interfaceClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception {
+
+ Object implementation =
+ Class.forName(implementationClassName).newInstance();
+ Class<Object> interfaceClass = interfaceClassName == null ? null :
+ (Class<Object>)Class.forName(interfaceClassName);
+
+ // Create the StandardMBean
+ StandardMBean standardMBean = new StandardMBean(
+ implementation,
+ interfaceClass,
+ isMXBean);
+
+ // Register the StandardMBean
+ mbeanServer.registerMBean(standardMBean, name);
+ }
+
+ /**
+ * Instantiates and registers a StandardMBean in the MBean server.
+ * The object will use standard JMX design pattern to determine
+ * the management interface associated with the given implementation.
+ */
+ @SuppressWarnings("unchecked")
+ public void createStandardMBean(
+ String implementationClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception {
+
+ createStandardMBean(implementationClassName, null, isMXBean, name);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/ServerDelegateMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2004, 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.security.Principal;
+import java.util.List;
+
+import javax.management.remote.JMXServiceURL ;
+import javax.management.ObjectName;
+
+@SqeDescriptorKey("INTERFACE ServerDelegateMBean")
+public interface ServerDelegateMBean {
+ @SqeDescriptorKey("ATTRIBUTE Address")
+ public void addAddress(JMXServiceURL url);
+
+ @SqeDescriptorKey("ATTRIBUTE Address")
+ public List<JMXServiceURL> getAddresses();
+
+ public String getPort();
+ public void setPort(String p);
+
+ public String getJavaVersion();
+
+ public void sqeJmxwsCredentialsProviderCalled();
+ public int getSqeJmxwsCredentialsProviderCallCount();
+
+ public void setJmxwsCredentialsProviderUrl(String url);
+ public String getJmxwsCredentialsProviderUrl();
+
+ public void testJMXAuthenticatorCalled();
+ public int getTestJMXAuthenticatorCallCount();
+
+ public void setTestJMXAuthenticatorPrincipal(Principal principal);
+ public String getTestJMXAuthenticatorPrincipalString();
+
+ public void createStandardMBean(
+ String implementationClassName,
+ String interfaceClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception;
+
+ public void createStandardMBean(
+ String implementationClassName,
+ boolean isMXBean,
+ ObjectName name)
+ throws Exception;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/Simple.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004, 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.beans.ConstructorProperties;
+import javax.management.ConstructorParameters;
+
+/**
+ * This class defines a simple standard MBean.
+ */
+public class Simple implements SimpleMBean {
+
+ private String attribute = "initial_value";
+ private boolean operationInvoked = false;
+ private boolean operation2Invoked = false;
+
+ @SqeDescriptorKey("NO PARAMETER CONSTRUCTOR Simple")
+ public Simple() {
+ }
+
+ @SqeDescriptorKey("TWO PARAMETERS CONSTRUCTOR Simple")
+ @ConstructorParameters({"unused1", "unused2"})
+ public Simple(@SqeDescriptorKey("CONSTRUCTOR PARAMETER unused1")int unused1,
+ @SqeDescriptorKey("CONSTRUCTOR PARAMETER unused2")int unused2) {
+ }
+
+ public String getAttribute() {
+ return attribute;
+ }
+ public void setAttribute(String s) {
+ attribute = s;
+ }
+ public boolean getOperationInvoked() {
+ return operationInvoked;
+ }
+ public boolean getOperation2Invoked() {
+ return operation2Invoked;
+ }
+
+ public void operation() {
+ operationInvoked = true;
+ return;
+ }
+
+ public String operation2(int i) {
+ operation2Invoked = true;
+ return String.valueOf(i);
+ }
+
+ public void reset() {
+ attribute = "initial_value";
+ operationInvoked = false;
+ operation2Invoked = false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/SimpleListener.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2003, 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.
+ */
+
+// JDK
+import java.util.Vector;
+
+// JMX
+import javax.management.NotificationListener;
+import javax.management.Notification;
+
+public class SimpleListener implements NotificationListener {
+ private boolean received = false;
+ private String type = null;
+ private Object handback = null;
+ private Vector<Object> handbacks = new Vector<Object>();
+ private int nbrec = 0;
+
+ public synchronized void handleNotification(Notification notification,
+ Object handback) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::handleNotification :" + notification);
+ try {
+ received = true;
+ type = notification.getType();
+ this.handback = handback;
+ handbacks.add(handback);
+ nbrec++;
+ notify();
+ } catch(Exception e) {
+ System.out.println("(ERROR) SimpleListener::handleNotification :"
+ + " Caught exception "
+ + e) ;
+ }
+ }
+
+ public synchronized boolean isNotificationReceived() {
+ boolean ret = received;
+ reset();
+ return ret;
+ }
+
+ public synchronized Object[] waitForMultiNotifications(int nb) {
+ while(true) {
+ if(nbrec < nb) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForMultiNotifications wait");
+ try {
+ wait();
+ } catch(InterruptedException ie) {
+ // OK : we wait for being interrupted
+ }
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForMultiNotifications wait over");
+ }
+ else
+ break;
+ }
+ Object[] ret = handbacks.toArray();
+ reset();
+ return ret;
+ }
+
+ private void reset() {
+ received = false;
+ handback = null;
+ handbacks.removeAllElements();
+ type = null;
+ }
+
+ public synchronized Object waitForNotificationHB() {
+ while(true) {
+ if(!received) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForNotificationHB wait");
+ try {
+ wait();
+ } catch(InterruptedException ie) {
+ // OK : we wait for being interrupted
+ }
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForNotificationHB received");
+ }
+ else
+ break;
+ }
+ Object ret = handback;
+ reset();
+ return ret;
+ }
+
+ public synchronized String waitForNotification() {
+ while(true) {
+ if(!received) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForNotification wait");
+ try {
+ wait();
+ } catch(InterruptedException ie) {
+ // OK : we wait for being interrupted
+ }
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "SimpleListener::waitForNotification received");
+ }
+ else
+ break;
+ }
+ String ret = type;
+ reset();
+ return ret;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/SimpleMBean.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004, 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.
+ */
+
+/**
+ * This interface defines a simple standard MBean.
+ */
+@SqeDescriptorKey("INTERFACE SimpleMBean")
+public interface SimpleMBean {
+
+ @SqeDescriptorKey("ATTRIBUTE Attribute")
+ public String getAttribute();
+
+ @SqeDescriptorKey("ATTRIBUTE Attribute")
+ public void setAttribute(String s);
+
+ @SqeDescriptorKey("ATTRIBUTE OperationInvoked")
+ public boolean getOperationInvoked();
+
+ @SqeDescriptorKey("ATTRIBUTE Operation2Invoked")
+ public boolean getOperation2Invoked();
+
+ // Void operation
+ // The associated MBeanOperationInfo is mapped to OpenMBeanOperationInfo
+ // => openType is added to the descriptor
+ @SqeDescriptorKey(value = "OPERATION operation",
+ descriptorFields = {"openType=SimpleType.VOID"})
+ public void operation();
+
+ @SqeDescriptorKey("OPERATION operation2")
+ public String operation2(int i);
+
+ // Void operation
+ // The associated MBeanOperationInfo is mapped to OpenMBeanOperationInfo
+ // => openType is added to the descriptor
+ @SqeDescriptorKey(value = "OPERATION reset",
+ descriptorFields = {"openType=SimpleType.VOID"})
+ public void reset();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/SqeDescriptorKey.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005, 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.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import javax.management.DescriptorKey;
+
+/**
+ * That annotation is usable everywhere DescriptorKey is (and even more).
+ * It is for use to test that you can retrieve the SqeDescriptorKey into the
+ * appropriate Descriptor instances as built by the JMX runtime.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SqeDescriptorKey {
+ @DescriptorKey("sqeDescriptorKey")
+ String value();
+
+ // List descriptor fields that may be added or may be updated
+ // when retrieving an MBeanInfo using a JMXWS connection compared to the
+ // MBeanInfo returned by a local MBeanServer.
+ // The annotation format is :
+ // <descriptorFieldName>=<descriptorFieldValue>
+ // The values actually handled by the test suite are :
+ // openType=SimpleType.VOID
+ @DescriptorKey("descriptorFields")
+ String[] descriptorFields() default {};
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/TestJMXAuthenticator.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2006, 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.security.Principal;
+
+import javax.management.Attribute;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.remote.JMXAuthenticator;
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
+
+public final class TestJMXAuthenticator implements JMXAuthenticator {
+
+ private String protocol = "";
+ private MBeanServer mbs = null;
+
+ public TestJMXAuthenticator() {
+ }
+
+ public TestJMXAuthenticator(String protocol) {
+ this.protocol = protocol;
+ }
+
+ public TestJMXAuthenticator(String protocol, MBeanServer mbs) {
+ this.protocol = protocol;
+ this.mbs = mbs;
+ }
+
+ public Subject authenticate(Object credentials) {
+
+ String credentials_username = "";
+ String credentials_password = "";
+ Principal aPrincipal = null;
+
+ credentials_username = ((String[]) credentials)[0];
+ credentials_password = ((String[]) credentials)[1];
+
+ String authenticated_username = System.getProperty("susername");
+ String authenticated_password = System.getProperty("spassword");
+ String principal = System.getProperty("principal");
+
+ System.out.println("TestJMXAuthenticator::authenticate: Start");
+ System.out.println("TestJMXAuthenticator::authenticate: credentials username = " +
+ credentials_username);
+ System.out.println("TestJMXAuthenticator::authenticate: credentials password = " +
+ credentials_password);
+ System.out.println("TestJMXAuthenticator::authenticate: authenticated username = " +
+ authenticated_username);
+ System.out.println("TestJMXAuthenticator::authenticate: authenticated password = " +
+ authenticated_password);
+ System.out.println("TestJMXAuthenticator::authenticate: principal used for " +
+ "authorization = " + principal);
+
+ if (credentials_username.equals(authenticated_username) &&
+ credentials_password.equals(authenticated_password)) {
+ System.out.println("TestJMXAuthenticator::authenticate: " +
+ "Authenticator should succeed");
+ } else {
+ System.out.println("TestJMXAuthenticator::authenticate: " +
+ "Authenticator should reject");
+ throw new SecurityException("TestJMXAuthenticator throws EXCEPTION");
+ }
+
+ // At this point, authentication has succeeded
+ // (no SecurityException thrown).
+ //
+ // If no authorization is required, the returned subject (empty or not)
+ // is useless.
+ // Otherwise, the returned subject must define a principal
+ // and authorization will be performed against this principal.
+ //
+ // Note that this custom JMXAuthenticator is used for test purpose and
+ // the username used to perform authentication may be different from the
+ // username used to perform authorization.
+ //
+ Subject subject = new Subject();
+
+ if (principal != null) {
+ System.out.println("TestJMXAuthenticator::authenticate: " +
+ "Add " + principal + " principal to the returned subject");
+ subject.getPrincipals().add(new JMXPrincipal(principal));
+ }
+
+ return subject;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/TestSampleLoginModule.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2006, 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.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+
+public final class TestSampleLoginModule implements LoginModule {
+
+ private Subject subject;
+ private CallbackHandler callbackHandler;
+ private Map<String, ?> sharedState;
+ private Map<String, ?> options;
+
+ public TestSampleLoginModule() {
+ }
+
+ public void initialize(Subject subject,
+ CallbackHandler callbackHandler,
+ Map<String,?> sharedState,
+ Map<String,?> options) {
+
+ this.subject = subject;
+ this.callbackHandler = callbackHandler;
+ this.sharedState = sharedState;
+ this.options = options;
+ }
+
+ /*
+ * Authenticate the user by comparing the values of the java properties
+ * (username and password) against the values of the credentials.
+ * */
+ public boolean login() throws LoginException {
+
+ String credentials_username = null;
+ String credentials_password = null;
+ String authenticated_username = System.getProperty("susername");
+ String authenticated_password = System.getProperty("spassword");
+
+ System.out.println("TestSampleLoginModule::login: Start");
+
+ // First retreive the credentials {username, password} from
+ // the callback handler
+ Callback[] callbacks = new Callback[2];
+ callbacks[0] = new NameCallback("username");
+ callbacks[1] = new PasswordCallback("password", false);
+ try {
+ callbackHandler.handle(callbacks);
+ credentials_username = ((NameCallback)callbacks[0]).getName();
+ credentials_password = new String(((PasswordCallback)callbacks[1]).
+ getPassword());
+ } catch (Exception e) {
+ throw new LoginException(e.toString());
+ }
+
+ System.out.println("TestSampleLoginModule::login: credentials username = " +
+ credentials_username);
+ System.out.println("TestSampleLoginModule::login: credentials password = " +
+ credentials_password);
+ System.out.println("TestSampleLoginModule::login: authenticated username = " +
+ authenticated_username);
+ System.out.println("TestSampleLoginModule::login: authenticated password = " +
+ authenticated_password);
+
+ if (credentials_username.equals(authenticated_username) &&
+ credentials_password.equals(authenticated_password)) {
+ System.out.println("TestSampleLoginModule::login: " +
+ "Authentication should succeed");
+ return true;
+ } else {
+ System.out.println("TestSampleLoginModule::login: " +
+ "Authentication should reject");
+ throw new LoginException("TestSampleLoginModule throws EXCEPTION");
+ }
+ }
+
+ public boolean commit() throws LoginException {
+ return true;
+ }
+
+ public boolean abort() throws LoginException {
+ return true;
+ }
+
+ public boolean logout() throws LoginException {
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/Utils.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2005, 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.util.Map;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.StringTokenizer;
+import java.lang.reflect.Method;
+import javax.management.remote.JMXConnectorServerMBean;
+
+// utility class for MXBean* tests coming from JMX Tonga test suite
+class Utils {
+
+ private static final String SERVER_SIDE_NAME = "-server";
+ private static final String CLIENT_SIDE_NAME = "-client";
+
+ // DEBUG is printed depending on the DEBUG and DEBUG_LEVEL JAVA property
+ private static final String DEBUG_HEADER = "[debug] ";
+
+ // DEBUG levels
+ private static int selectedDebugLevel = 0;
+ static final int DEBUG_STANDARD = 1;
+ static final int DEBUG_VERBOSE = 2; // Mainly used for stress tests
+ static final int DEBUG_ALL = DEBUG_STANDARD | DEBUG_VERBOSE;
+
+ static void parseDebugProperties() {
+ int level = 0;
+ Properties p = System.getProperties();
+
+ // get selected levels
+ if (p.getProperty("DEBUG_STANDARD") != null) {
+ level |= DEBUG_STANDARD;
+ }
+
+ if (p.getProperty("DEBUG_VERBOSE") != null) {
+ level |= DEBUG_VERBOSE;
+ }
+
+ if (p.getProperty("DEBUG_ALL") != null) {
+ level |= DEBUG_ALL;
+ }
+
+ selectedDebugLevel = level;
+ }
+
+ /**
+ * Reproduces the original parsing and collection of test parameters
+ * from the DTonga JMX test suite.
+ *
+ * Collects passed args and returns them in a map(argname, value) structure,
+ * which will be then propagated as necessary to various called methods.
+ */
+ static Map<String, Object> parseParameters(String args[])
+ throws Exception {
+ Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Start");
+ HashMap<String, Object> map = new HashMap<>();
+
+ for ( int i = 0; i < args.length; i++ ) {
+ if ( args[i].trim().startsWith("-") ) {
+ if ((i+1) < args.length && !args[i+1].startsWith("-") ) {
+ Utils.debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with value " +
+ args[i+1]) ;
+ map.put(args[i].trim(), args[i+1].trim()) ;
+ } else if ((i+1) < args.length && args[i+1].startsWith("-") ||
+ (i+1) == args.length ) {
+ Utils.debug(DEBUG_STANDARD,
+ "TestRoot::parseParameters: added in map = " +
+ args[i] +
+ " with null value") ;
+ map.put(args[i].trim(), null) ;
+ } else {
+ System.out.println(
+ "TestRoot::parseParameters: (WARNING) not added in map = " +
+ args[i]) ;
+ }
+ }
+ }
+
+ Utils.debug(DEBUG_STANDARD, "TestRoot::parseParameters: Done") ;
+ return map ;
+ }
+
+ // Parse server parameters and put them in passed serverMap
+ static int parseServerParameters(String args[],
+ String serverSideName,
+ Map<String, Object> serverMap )
+ throws Exception {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ serverSideName + "::parseServerParameters: Start");
+
+ int nextIndex = 0;
+ boolean seenServerFlag = false;
+
+ for ( int i = 0; i < args.length; i++ ) {
+ // Case of reaching "-server" flag parameter
+ if (args[i].equals(SERVER_SIDE_NAME)) {
+ if (!seenServerFlag) {
+ seenServerFlag = true;
+ continue;
+ } else {
+ // Already parsing server params, invalid params list
+ Utils.debug(Utils.DEBUG_STANDARD,
+ serverSideName + "::parseParameters: Invalid " +
+ args[i] + " parameter detected in " +
+ SERVER_SIDE_NAME + " parameters list");
+ nextIndex = -1;
+ throw new RuntimeException("Invalid Parameter list");
+ }
+ }
+
+ // Case of reaching "-client" flag parameter
+ if (args[i].equals(CLIENT_SIDE_NAME)) {
+ // While parsing server parameters, then parsing is done.
+ Utils.debug(Utils.DEBUG_STANDARD,
+ serverSideName + "::parseServerParameters: Parsing of " +
+ SERVER_SIDE_NAME + " parameters done.");
+ return i;
+ }
+
+ i = parseParamAtIndex(args, i, serverMap);
+ nextIndex = i;
+ }
+
+ Utils.debug(Utils.DEBUG_STANDARD,
+ serverSideName + "::parseServerParameters: Parsing of parameters done");
+
+ return nextIndex;
+ }
+
+ // Parse client parameters and put them in passed clientMap
+ static void parseClientParameters(String args[],
+ String clientSideName,
+ Map<String, Object> clientMap )
+ throws Exception {
+
+ Utils.debug(Utils.DEBUG_STANDARD,
+ clientSideName + "::parseClientParameters: Start");
+
+ boolean seenClientFlag = false;
+
+ for ( int i = 0; i < args.length; i++ ) {
+ // Case of reaching "-client" flag parameter
+ if (args[i].equals(CLIENT_SIDE_NAME)) {
+ if (!seenClientFlag) {
+ seenClientFlag = true;
+ continue;
+ } else {
+ // Already parsing client params, invalid params list
+ Utils.debug(Utils.DEBUG_STANDARD,
+ clientSideName + "::parseClientParameters: Invalid " +
+ CLIENT_SIDE_NAME + " parameter detected in " +
+ CLIENT_SIDE_NAME + " parameters list.");
+ throw new RuntimeException("Invalid parameter in " +
+ clientSideName + " parameter list");
+ }
+ }
+
+ // Case of reaching "-server" flag parameter
+ if (args[i].equals(SERVER_SIDE_NAME)) {
+ // While parsing client parameters, invalid parameter list.
+ Utils.debug(Utils.DEBUG_STANDARD,
+ clientSideName + "::parseClientParameters: Invalid " +
+ SERVER_SIDE_NAME + " parameter inside " +
+ CLIENT_SIDE_NAME + " parameters list.");
+ throw new RuntimeException("Invalid parameter in " +
+ clientSideName + " parameter list");
+ }
+
+ i = parseParamAtIndex(args, i, clientMap);
+ }
+
+ Utils.debug(Utils.DEBUG_STANDARD,
+ clientSideName + "::parseClientParameters: Parsing of parameters done.");
+ }
+
+ // Add param found at index to passed map
+ // We only accept either "-param value" or "-param" form.
+ // The "value" form is invalid but just ignored.
+ private static int parseParamAtIndex(String args[],
+ int index,
+ Map<String, Object> map) {
+
+ if (args[index].trim().startsWith("-") ) {
+ // Case of a "-param value" form
+ if ((index+1) < args.length && !args[index+1].startsWith("-") ) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "TestRoot::parseParamAtIndex: added in map = "
+ + args[index]
+ + " with value "
+ + args[index+1]) ;
+ // adding ("param", value) to the passed map
+ map.put(args[index].trim(), args[index+1].trim()) ;
+ // value should not be parsed a second time
+ return index+1;
+ }
+ // Case of a "-param" form (flag parameter)
+ else if (((index+1) < args.length && args[index+1].startsWith("-")) ||
+ (index+1) == args.length ) {
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "TestRoot::parseParamAtIndex: added in map = "
+ + args[index]
+ + " with null value") ;
+ // adding ("param", null) to passed map
+ map.put(args[index].trim(), null) ;
+ }
+ } else {
+ // Unsupported "value" alone parameter
+ Utils.debug(Utils.DEBUG_STANDARD,
+ "TestRoot::parseParamAtIndex: invalid " +
+ " value-alone \"" + args[index] + "\" parameter." +
+ " Parameter ignored.");
+ }
+
+ return index;
+ }
+
+ /**
+ * This method is to be used in all tests to print anything
+ * that is temporary.
+ * Printing is done only when debug is activated by the property DEBUG.
+ * Printing depends also on the DEBUG_LEVEL property.
+ * Here it encapsulates a System.out.println.
+ */
+ static void debug(int level, String line) {
+ if ((selectedDebugLevel & level) != 0) {
+ System.out.println(DEBUG_HEADER + line);
+ }
+ }
+
+ /**
+ * Do print stack trace when withStack is true.
+ * Does try to call getTargetException() and getTargetError() then
+ * print embedded stacks in the case of an Exception wrapping
+ * another Exception or an Error. Recurse until no more wrapping
+ * is found.
+ */
+ static void printThrowable(Throwable theThro, boolean withStack) {
+ try {
+ if (withStack) {
+ theThro.printStackTrace(System.out);
+ }
+ if (theThro instanceof Exception) {
+ Exception t = (Exception) theThro;
+ Method target = null;
+ String blank = " ";
+ try {
+ target = t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not
+ }
+ System.out.println(blank + t.getClass() + "==>" + t.getMessage());
+ while (target != null) {
+ try {
+ t = (Exception) target.invoke(t,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ t = null;
+ }
+ try {
+ if (t != null) {
+ blank = blank + " ";
+ System.out.println(blank + t.getClass() + "==>" +
+ t.getMessage());
+ try {
+ target =
+ t.getClass().getMethod("getTargetException",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetException method could be there or not }
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+
+ // We may have exceptions wrapping an Error then it is
+ // getTargetError that is likely to be called
+ try {
+ target = ((Exception) theThro).getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ Throwable err = theThro;
+ while (target != null) {
+ try {
+ err = (Error) target.invoke(err,
+ (java.lang.Object[]) null);
+ } catch (Exception ee) {
+ err = null;
+ }
+ try {
+ if (err != null) {
+ blank = blank + " ";
+ System.out.println(blank + err.getClass() + "==>" +
+ err.getMessage());
+ if (withStack) {
+ err.printStackTrace(System.out);
+ }
+ try {
+ target = err.getClass().getMethod("getTargetError",
+ (java.lang.Class<?>[]) null);
+ } catch (Exception ee) {
+ // OK: getTargetError method could be there or not
+ }
+ } else {
+ target = null;
+ }
+ } catch (Exception ee) {
+ target = null;
+ }
+ }
+ } else {
+ System.out.println("Throwable is : " + theThro);
+ }
+ } catch (Throwable x) {
+ System.out.println("Exception : raised in printException : " + x);
+ }
+ }
+
+ /**
+ * Wait up to maxTimeInSeconds second(s) the given JMX connector server
+ * comes up (which means isActive returns true).
+ * If it fails to do so we throw a RunTime exception.
+ */
+ static void waitReady(JMXConnectorServerMBean server,
+ int maxTimeInSeconds) throws Exception {
+ int elapsed = 0;
+
+ while (!server.isActive() && elapsed < maxTimeInSeconds) {
+ Thread.sleep(1000);
+ elapsed++;
+ }
+
+ if (server.isActive()) {
+ String message = "Utils::waitReady: JMX connector server came up";
+ if ( elapsed == 0) {
+ message += " immediately";
+ } else {
+ message += " after " + elapsed + " seconds";
+ }
+ message += " [" + server.getAddress() + "]";
+ Utils.debug(DEBUG_STANDARD, message);
+ } else {
+ String message = "Utils::waitReady: (ERROR) JMX connector" +
+ " server didn't come up after " + elapsed + " seconds [" +
+ server.getAddress() + "]";
+ System.out.println(message);
+ throw new RuntimeException(message);
+ }
+ }
+
+ /**
+ * This method is used to compare the specified Throwable and possibly
+ * the derived causes to the specified String argument.
+ * The expected String argument format is :
+ * throwable_1;throwable_2;...;throwable_N
+ * where throwable_i can be :
+ * - either a throwable class name
+ * - or the "*" character meaning several unknown throwable class names
+ * This character must be followed by a throwable class name
+ */
+ static boolean compareThrowable(
+ Throwable t,
+ String expectedThrowable) {
+
+ // First parse the expectedThrowable String
+ StringTokenizer tokenizer = new StringTokenizer(expectedThrowable, ";");
+ String token = null;
+
+ try {
+ while (tokenizer.hasMoreTokens()) {
+ token = tokenizer.nextToken();
+ if (!token.equals("*")) {
+ if (!Class.forName(token).isInstance(t)) {
+ return false;
+ }
+ } else {
+ token = tokenizer.nextToken();
+ while (!Class.forName(token).isInstance(t)) {
+ t = t.getCause();
+ if (t == null) {
+ return false;
+ }
+ }
+ }
+ t = t.getCause();
+ }
+ } catch (ClassNotFoundException cnfe) {
+ String msg = "Expected throwable class(es) " + expectedThrowable +
+ " cannot be located";
+ System.out.println(msg);
+ throw new IllegalArgumentException(msg);
+ }
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/access.properties Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,11 @@
+# Access control file for SQE tests.
+
+# Default username
+SQE_username readwrite create Simple
+
+# Functional authorization tests
+username1 readwrite create Simple
+username2 readonly
+username3 readonly
+username4 readwrite create Simple
+username5 readwrite create Simple
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/java.policy.authorization Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,98 @@
+// Standard extensions get all permissions by default
+
+grant codeBase "file:${java.home}/lib/ext/*" {
+ permission java.security.AllPermission;
+};
+
+// default permissions granted to all domains
+grant {
+ // Allows any thread to stop itself using the java.lang.Thread.stop()
+ // method that takes no argument.
+ // Note that this permission is granted by default only to remain
+ // backwards compatible.
+ // It is strongly recommended that you either remove this permission
+ // from this policy file or further restrict it to code sources
+ // that you specify, because Thread.stop() is potentially unsafe.
+ // See "http://java.sun.com/notes" for more information.
+ permission java.lang.RuntimePermission "stopThread";
+
+ // allows anyone to listen on un-privileged ports
+ permission java.net.SocketPermission "localhost:1024-", "listen";
+
+ // "standard" properies that can be read by anyone
+
+ permission java.util.PropertyPermission "java.version", "read";
+ permission java.util.PropertyPermission "java.vendor", "read";
+ permission java.util.PropertyPermission "java.vendor.url", "read";
+ permission java.util.PropertyPermission "java.class.version", "read";
+ permission java.util.PropertyPermission "os.name", "read";
+ permission java.util.PropertyPermission "os.version", "read";
+ permission java.util.PropertyPermission "os.arch", "read";
+ permission java.util.PropertyPermission "file.separator", "read";
+ permission java.util.PropertyPermission "path.separator", "read";
+ permission java.util.PropertyPermission "line.separator", "read";
+
+ permission java.util.PropertyPermission "java.specification.version", "read";
+ permission java.util.PropertyPermission "java.specification.vendor", "read";
+ permission java.util.PropertyPermission "java.specification.name", "read";
+
+ permission java.util.PropertyPermission "java.vm.specification.version", "read";
+ permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
+ permission java.util.PropertyPermission "java.vm.specification.name", "read";
+ permission java.util.PropertyPermission "java.vm.version", "read";
+ permission java.util.PropertyPermission "java.vm.vendor", "read";
+ permission java.util.PropertyPermission "java.vm.name", "read";
+
+ permission java.io.FilePermission "*","read,write";
+
+};
+
+grant codeBase "file:/-" {
+ permission java.security.AllPermission;
+ permission java.io.FilePermission "*","read,write";
+};
+
+grant principal javax.management.remote.JMXPrincipal "SQE_username" {
+ permission javax.management.MBeanServerPermission "*";
+ permission javax.management.MBeanPermission "Simple", "instantiate";
+ permission javax.management.MBeanPermission "Simple", "registerMBean";
+};
+
+grant principal javax.management.remote.JMXPrincipal "username1" {
+ //
+ // JMXPrincipals "username1" has all permissions.
+ //
+ permission java.security.AllPermission;
+};
+
+grant principal javax.management.remote.JMXPrincipal "username2" {
+ //
+ // JMXPrincipals "username2" has all permissions.
+ //
+ permission java.security.AllPermission;
+};
+
+grant principal javax.management.remote.JMXPrincipal "username3" {
+ //
+ // JMXPrincipals "username3" has some permissions.
+ //
+ permission javax.management.MBeanPermission "Simple", "instantiate";
+ permission javax.management.MBeanPermission "Simple", "registerMBean";
+ permission javax.management.MBeanPermission "Simple", "setAttribute";
+ permission javax.management.MBeanPermission "Simple", "invoke";
+};
+
+grant principal javax.management.remote.JMXPrincipal "username4" {
+ //
+ // JMXPrincipals "username4" has all permissions.
+ //
+ permission javax.management.MBeanPermission "Simple", "instantiate";
+ permission javax.management.MBeanPermission "Simple", "registerMBean";
+ permission javax.management.MBeanPermission "Simple", "invoke";
+};
+
+grant principal javax.management.remote.JMXPrincipal "username5" {
+ //
+ // JMXPrincipals "username5" has no permissions.
+ //
+};
Binary file jdk/test/javax/management/security/keystoreAgent has changed
Binary file jdk/test/javax/management/security/keystoreClient has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/login.config Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,8 @@
+PasswordFileAuthentication {
+ com.sun.jmx.remote.security.FileLoginModule required
+ passwordFile="${password.file}";
+};
+
+SampleLoginModule {
+ TestSampleLoginModule required;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/security/password.properties Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,12 @@
+# Password file for default SQE username.
+SQE_username SQE_password
+
+# Functional authorization tests
+username1 password1
+username2 password2
+username3 password3
+username4 password4
+username5 password5
+username6 password6
+
+usernameFileLoginModule passwordFileLoginModule
Binary file jdk/test/javax/management/security/truststoreAgent has changed
Binary file jdk/test/javax/management/security/truststoreClient has changed
--- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,6 +28,7 @@
* @test
* @bug 8043758
* @summary Datagram Transport Layer Security (DTLS)
+ * @modules java.base/sun.security.util
* @run main/othervm DTLSOverDatagram
*/
@@ -40,7 +41,7 @@
import javax.net.ssl.*;
import java.util.concurrent.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/**
* An example to show the way to use SSLEngine in datagram connections.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/TLSv12/SignatureAlgorithms.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,592 @@
+/*
+ * 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.
+ */
+
+//
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+//
+
+/*
+ * @test
+ * @bug 8049321
+ * @summary Support SHA256WithDSA in JSSE
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-224,SHA-256"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-1,SHA-224"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-1,SHA-256"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-224,SHA-256"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-1,SHA-224"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+ * @run main/othervm SignatureAlgorithms PKIX "SHA-1,SHA-256"
+ * TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
+ */
+
+import java.net.*;
+import java.util.*;
+import java.io.*;
+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.X509Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.*;
+import java.security.interfaces.*;
+
+public class SignatureAlgorithms {
+
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ // Certificates and key (DSA) used in the test.
+ static String trustedCertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDYTCCAyGgAwIBAgIJAK8/gw6zg/DPMAkGByqGSM44BAMwOzELMAkGA1UEBhMC\n" +
+ "VVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNl\n" +
+ "MB4XDTE1MTIwMzEzNTIyNVoXDTM2MTExMjEzNTIyNVowOzELMAkGA1UEBhMCVVMx\n" +
+ "DTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNlMIIB\n" +
+ "uDCCASwGByqGSM44BAEwggEfAoGBAPH+b+GSMX6KS7jXDRevzc464DFG4X+uxu5V\n" +
+ "b3U4yhsU8A8cuH4gwin6L/IDkmZQ7N0zC0jRsiGVSMsFETTq10F39pH2eBfUv/hJ\n" +
+ "cLfBnIjBEtVqV/dExK88Hul2sZ4mQihQ4issPl7hsroS9EWYicnX0oNAqAB9PO5Y\n" +
+ "zKbfpL7TAhUA13WW48rln2UP/LaAgtnzKhqcNtMCgYEA3Rv0GirTbAaor8iURd82\n" +
+ "b5FlDTevOCTuq7ZIpfZVV30neS7cBYNet6m/3/4cfUlbbrqhbqIJ2I+I81drnN0Y\n" +
+ "lyN4KkuxEcB6OTwfWkIUj6rvPaCQrBH8Q213bDq3HHtYNaP8OoeQUyVXW+SEGADC\n" +
+ "J1+z8uqP3lIB6ltdgOiV/GQDgYUAAoGBAOXRppuJSGdt6AiZkb81P1DCUgIUlZFI\n" +
+ "J9GxWrjbbHDmGllMwPNhK6dU7LJKJJuYVPW+95rUGlSJEjRqSlHuyHkNb6e3e7qx\n" +
+ "tmx1/oIyq+oLult50hBS7uBvLLR0JbIKjBzzkudL8Rjze4G/Wq7KDM2T1JOP49tW\n" +
+ "eocCvaC8h8uQo4GtMIGqMB0GA1UdDgQWBBT17HcqLllsqnZzP+kElcGcBGmubjBr\n" +
+ "BgNVHSMEZDBigBT17HcqLllsqnZzP+kElcGcBGmubqE/pD0wOzELMAkGA1UEBhMC\n" +
+ "VVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNl\n" +
+ "ggkArz+DDrOD8M8wDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwCQYHKoZI\n" +
+ "zjgEAwMvADAsAhQ6Y1I6LtIEBMqNo8o6GIe4LLEJuwIUbVQUKi8tvtWyRoxm8AFV\n" +
+ "0axJYUU=\n" +
+ "-----END CERTIFICATE-----";
+
+ static String[] targetCertStr = {
+ // DSA-SHA1
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDKTCCAumgAwIBAgIJAOy5c0b+8stFMAkGByqGSM44BAMwOzELMAkGA1UEBhMC\n" +
+ "VVMxDTALBgNVBAoTBEphdmExHTAbBgNVBAsTFFN1bkpTU0UgVGVzdCBTZXJpdmNl\n" +
+ "MB4XDTE1MTIwMzEzNTIyNVoXDTM1MDgyMDEzNTIyNVowTzELMAkGA1UEBhMCVVMx\n" +
+ "DTALBgNVBAoMBEphdmExHTAbBgNVBAsMFFN1bkpTU0UgVGVzdCBTZXJpdmNlMRIw\n" +
+ "EAYDVQQDDAlsb2NhbGhvc3QwggG3MIIBLAYHKoZIzjgEATCCAR8CgYEA8f5v4ZIx\n" +
+ "fopLuNcNF6/NzjrgMUbhf67G7lVvdTjKGxTwDxy4fiDCKfov8gOSZlDs3TMLSNGy\n" +
+ "IZVIywURNOrXQXf2kfZ4F9S/+Elwt8GciMES1WpX90TErzwe6XaxniZCKFDiKyw+\n" +
+ "XuGyuhL0RZiJydfSg0CoAH087ljMpt+kvtMCFQDXdZbjyuWfZQ/8toCC2fMqGpw2\n" +
+ "0wKBgQDdG/QaKtNsBqivyJRF3zZvkWUNN684JO6rtkil9lVXfSd5LtwFg163qb/f\n" +
+ "/hx9SVtuuqFuognYj4jzV2uc3RiXI3gqS7ERwHo5PB9aQhSPqu89oJCsEfxDbXds\n" +
+ "Orcce1g1o/w6h5BTJVdb5IQYAMInX7Py6o/eUgHqW12A6JX8ZAOBhAACgYB+zYqn\n" +
+ "jJwG4GZpBIN/6qhzbp0flChsV+Trlu0SL0agAQzb6XdI/4JnO87Pgbxaxh3VNAj3\n" +
+ "3+Ghr1NLBuBfTKzJ4j9msWT3EpLupkMyNtXvBYM0iyMrll67lSjMdv++wLEw35Af\n" +
+ "/bzVcjGyA5Q0i0cuEzDmHTVfi0OydynbwSLxtKNjMGEwCwYDVR0PBAQDAgPoMB0G\n" +
+ "A1UdDgQWBBQXJI8AxM0qsYCbbkIMuI5zJ+nMEDAfBgNVHSMEGDAWgBT17HcqLlls\n" +
+ "qnZzP+kElcGcBGmubjASBgNVHREBAf8ECDAGhwR/AAABMAkGByqGSM44BAMDLwAw\n" +
+ "LAIUXgyJ0xll4FrZAKXi8bj7Kiz+SA4CFH9WCSZIBYA9lmJkiTgRS7iM/6IC\n" +
+ "-----END CERTIFICATE-----",
+
+ // DSA-SHA224
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDLzCCAuugAwIBAgIJAOy5c0b+8stGMAsGCWCGSAFlAwQDATA7MQswCQYDVQQG\n" +
+ "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+ "Y2UwHhcNMTUxMjAzMTU0NDM5WhcNMzUwODIwMTU0NDM5WjBPMQswCQYDVQQGEwJV\n" +
+ "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +
+ "EjAQBgNVBAMMCWxvY2FsaG9zdDCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQDx/m/h\n" +
+ "kjF+iku41w0Xr83OOuAxRuF/rsbuVW91OMobFPAPHLh+IMIp+i/yA5JmUOzdMwtI\n" +
+ "0bIhlUjLBRE06tdBd/aR9ngX1L/4SXC3wZyIwRLValf3RMSvPB7pdrGeJkIoUOIr\n" +
+ "LD5e4bK6EvRFmInJ19KDQKgAfTzuWMym36S+0wIVANd1luPK5Z9lD/y2gILZ8yoa\n" +
+ "nDbTAoGBAN0b9Boq02wGqK/IlEXfNm+RZQ03rzgk7qu2SKX2VVd9J3ku3AWDXrep\n" +
+ "v9/+HH1JW266oW6iCdiPiPNXa5zdGJcjeCpLsRHAejk8H1pCFI+q7z2gkKwR/ENt\n" +
+ "d2w6txx7WDWj/DqHkFMlV1vkhBgAwidfs/Lqj95SAepbXYDolfxkA4GEAAKBgA81\n" +
+ "CJKEv+pwiqYgxtw/9rkQ9748WP3mKrEC06kjUG+94/Z9dQloNFFfj6LiO1bymc5l\n" +
+ "6QIR8XCi4Po3N80K3+WxhBGFhY+RkVWTh43JV8epb41aH2qiWErarBwBGEh8LyGT\n" +
+ "i30db+Nkz2gfvyz9H/9T0jmYgfLEOlMCusali1qHo2MwYTALBgNVHQ8EBAMCA+gw\n" +
+ "HQYDVR0OBBYEFBqSP0S4+X+zOCTEnlp2hbAjV/W5MB8GA1UdIwQYMBaAFPXsdyou\n" +
+ "WWyqdnM/6QSVwZwEaa5uMBIGA1UdEQEB/wQIMAaHBH8AAAEwCwYJYIZIAWUDBAMB\n" +
+ "AzEAMC4CFQChiRaOnAnsCSJFwdpK22jSxU/mhQIVALgLbj/G39+1Ej8UuSWnEQyU\n" +
+ "4DA+\n" +
+ "-----END CERTIFICATE-----",
+
+ // DSA-SHA256
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIDLTCCAuugAwIBAgIJAOy5c0b+8stHMAsGCWCGSAFlAwQDAjA7MQswCQYDVQQG\n" +
+ "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" +
+ "Y2UwHhcNMTUxMjAzMTU0NjUxWhcNMzUwODIwMTU0NjUxWjBPMQswCQYDVQQGEwJV\n" +
+ "UzENMAsGA1UECgwESmF2YTEdMBsGA1UECwwUU3VuSlNTRSBUZXN0IFNlcml2Y2Ux\n" +
+ "EjAQBgNVBAMMCWxvY2FsaG9zdDCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQDx/m/h\n" +
+ "kjF+iku41w0Xr83OOuAxRuF/rsbuVW91OMobFPAPHLh+IMIp+i/yA5JmUOzdMwtI\n" +
+ "0bIhlUjLBRE06tdBd/aR9ngX1L/4SXC3wZyIwRLValf3RMSvPB7pdrGeJkIoUOIr\n" +
+ "LD5e4bK6EvRFmInJ19KDQKgAfTzuWMym36S+0wIVANd1luPK5Z9lD/y2gILZ8yoa\n" +
+ "nDbTAoGBAN0b9Boq02wGqK/IlEXfNm+RZQ03rzgk7qu2SKX2VVd9J3ku3AWDXrep\n" +
+ "v9/+HH1JW266oW6iCdiPiPNXa5zdGJcjeCpLsRHAejk8H1pCFI+q7z2gkKwR/ENt\n" +
+ "d2w6txx7WDWj/DqHkFMlV1vkhBgAwidfs/Lqj95SAepbXYDolfxkA4GEAAKBgEF7\n" +
+ "2qiYxGrjX4KCOy0k5nK/RYlgLy4gYDChihQpiaa+fbA5JOBOxPWsh7rdtmJuDrEJ\n" +
+ "keacU223+DIhOKC49fa+EvhLNqo6U1oPn8n/yvBsvvnWkcynw5KfNzaLlaPmzugh\n" +
+ "v9xl/GhyZNAXc1QUcW3C+ceHVNrKnkfbTKZz5eRSo2MwYTALBgNVHQ8EBAMCA+gw\n" +
+ "HQYDVR0OBBYEFNMkPrt40oO9Dpy+bcbQdEvOlNlyMB8GA1UdIwQYMBaAFPXsdyou\n" +
+ "WWyqdnM/6QSVwZwEaa5uMBIGA1UdEQEB/wQIMAaHBH8AAAEwCwYJYIZIAWUDBAMC\n" +
+ "Ay8AMCwCFCvA2QiKSe/n+6GqSYQwgQ/zL5M9AhQfSiuWdMJKWpgPJKakvzhBUbMb\n" +
+ "vA==\n" +
+ "-----END CERTIFICATE-----"};
+
+ // Private key in the format of PKCS#8, key size is 1024 bits.
+ static String[] targetPrivateKey = {
+ // For cert DSA-SHA1
+ "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAPH+b+GSMX6KS7jXDRevzc464DFG\n" +
+ "4X+uxu5Vb3U4yhsU8A8cuH4gwin6L/IDkmZQ7N0zC0jRsiGVSMsFETTq10F39pH2\n" +
+ "eBfUv/hJcLfBnIjBEtVqV/dExK88Hul2sZ4mQihQ4issPl7hsroS9EWYicnX0oNA\n" +
+ "qAB9PO5YzKbfpL7TAhUA13WW48rln2UP/LaAgtnzKhqcNtMCgYEA3Rv0GirTbAao\n" +
+ "r8iURd82b5FlDTevOCTuq7ZIpfZVV30neS7cBYNet6m/3/4cfUlbbrqhbqIJ2I+I\n" +
+ "81drnN0YlyN4KkuxEcB6OTwfWkIUj6rvPaCQrBH8Q213bDq3HHtYNaP8OoeQUyVX\n" +
+ "W+SEGADCJ1+z8uqP3lIB6ltdgOiV/GQEFgIUOiB7J/lrFrNduQ8nDNTe8VspoAI=",
+
+ // For cert DSA-SHA224
+ "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAPH+b+GSMX6KS7jXDRevzc464DFG\n" +
+ "4X+uxu5Vb3U4yhsU8A8cuH4gwin6L/IDkmZQ7N0zC0jRsiGVSMsFETTq10F39pH2\n" +
+ "eBfUv/hJcLfBnIjBEtVqV/dExK88Hul2sZ4mQihQ4issPl7hsroS9EWYicnX0oNA\n" +
+ "qAB9PO5YzKbfpL7TAhUA13WW48rln2UP/LaAgtnzKhqcNtMCgYEA3Rv0GirTbAao\n" +
+ "r8iURd82b5FlDTevOCTuq7ZIpfZVV30neS7cBYNet6m/3/4cfUlbbrqhbqIJ2I+I\n" +
+ "81drnN0YlyN4KkuxEcB6OTwfWkIUj6rvPaCQrBH8Q213bDq3HHtYNaP8OoeQUyVX\n" +
+ "W+SEGADCJ1+z8uqP3lIB6ltdgOiV/GQEFgIUOj9F5mxWd9W1tiLSdsOAt8BUBzE=",
+
+ // For cert DSA-SHA256
+ "MIIBSwIBADCCASwGByqGSM44BAEwggEfAoGBAPH+b+GSMX6KS7jXDRevzc464DFG\n" +
+ "4X+uxu5Vb3U4yhsU8A8cuH4gwin6L/IDkmZQ7N0zC0jRsiGVSMsFETTq10F39pH2\n" +
+ "eBfUv/hJcLfBnIjBEtVqV/dExK88Hul2sZ4mQihQ4issPl7hsroS9EWYicnX0oNA\n" +
+ "qAB9PO5YzKbfpL7TAhUA13WW48rln2UP/LaAgtnzKhqcNtMCgYEA3Rv0GirTbAao\n" +
+ "r8iURd82b5FlDTevOCTuq7ZIpfZVV30neS7cBYNet6m/3/4cfUlbbrqhbqIJ2I+I\n" +
+ "81drnN0YlyN4KkuxEcB6OTwfWkIUj6rvPaCQrBH8Q213bDq3HHtYNaP8OoeQUyVX\n" +
+ "W+SEGADCJ1+z8uqP3lIB6ltdgOiV/GQEFgIUQ2WGgg+OO39Aujj0e4lM4pP4/9g="};
+
+
+ static char passphrase[] = "passphrase".toCharArray();
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile boolean serverReady = false;
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+
+ SSLContext context = generateSSLContext(
+ null, targetCertStr, targetPrivateKey);
+ SSLServerSocketFactory sslssf = context.getServerSocketFactory();
+ try (SSLServerSocket sslServerSocket =
+ (SSLServerSocket)sslssf.createServerSocket(serverPort)) {
+
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) {
+ sslSocket.setEnabledCipherSuites(
+ sslSocket.getSupportedCipherSuites());
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslIS.read();
+ sslOS.write('A');
+ sslOS.flush();
+
+ dumpSignatureAlgorithms(sslSocket);
+ }
+ }
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ SSLContext context = generateSSLContext(trustedCertStr, null, null);
+ SSLSocketFactory sslsf = context.getSocketFactory();
+
+ try (SSLSocket sslSocket =
+ (SSLSocket)sslsf.createSocket("localhost", serverPort)) {
+
+ // enable TLSv1.2 only
+ sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
+
+ // enable a block cipher
+ sslSocket.setEnabledCipherSuites(new String[] {cipherSuite});
+
+ InputStream sslIS = sslSocket.getInputStream();
+ OutputStream sslOS = sslSocket.getOutputStream();
+
+ sslOS.write('B');
+ sslOS.flush();
+ sslIS.read();
+
+ dumpSignatureAlgorithms(sslSocket);
+ }
+ }
+
+ static void dumpSignatureAlgorithms(SSLSocket sslSocket) throws Exception {
+
+ boolean isClient = sslSocket.getUseClientMode();
+ String mode = "[" + (isClient ? "Client" : "Server") + "]";
+ ExtendedSSLSession session =
+ (ExtendedSSLSession)sslSocket.getSession();
+ String[] signAlgs = session.getLocalSupportedSignatureAlgorithms();
+ System.out.println(
+ mode + " local supported signature algorithms: " +
+ Arrays.asList(signAlgs));
+
+ if (!isClient) {
+ signAlgs = session.getPeerSupportedSignatureAlgorithms();
+ System.out.println(
+ mode + " peer supported signature algorithms: " +
+ Arrays.asList(signAlgs));
+ } else {
+ Certificate[] serverCerts = session.getPeerCertificates();
+
+ // server should always send the authentication cert.
+ String sigAlg = ((X509Certificate)serverCerts[0]).getSigAlgName();
+ System.out.println(
+ mode + " the signature algorithm of server certificate: " +
+ sigAlg);
+ if (sigAlg.contains("SHA1")) {
+ if (disabledAlgorithms.contains("SHA-1")) {
+ throw new Exception(
+ "Not the expected server certificate. " +
+ "SHA-1 should be disabled");
+ }
+ } else if (sigAlg.contains("SHA224")) {
+ if (disabledAlgorithms.contains("SHA-224")) {
+ throw new Exception(
+ "Not the expected server certificate. " +
+ "SHA-224 should be disabled");
+ }
+ } else { // SHA-256
+ if (disabledAlgorithms.contains("SHA-256")) {
+ throw new Exception(
+ "Not the expected server certificate. " +
+ "SHA-256 should be disabled");
+ }
+ }
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+ private static String tmAlgorithm; // trust manager
+ private static String disabledAlgorithms; // disabled algorithms
+ private static String cipherSuite; // cipher suite
+
+ private static void parseArguments(String[] args) {
+ tmAlgorithm = args[0];
+ disabledAlgorithms = args[1];
+ cipherSuite = args[2];
+ }
+
+ private static SSLContext generateSSLContext(String trustedCertStr,
+ String[] keyCertStrs, String[] keySpecStrs) throws Exception {
+
+ // generate certificate from cert string
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+
+ // create a key store
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+
+ // import the trused cert
+ Certificate trusedCert = null;
+ ByteArrayInputStream is = null;
+ if (trustedCertStr != null) {
+ is = new ByteArrayInputStream(trustedCertStr.getBytes());
+ trusedCert = cf.generateCertificate(is);
+ is.close();
+
+ ks.setCertificateEntry("DSA Signer", trusedCert);
+ }
+
+ if (keyCertStrs != null && keyCertStrs.length != 0) {
+ for (int i = 0; i < keyCertStrs.length; i++) {
+ String keyCertStr = keyCertStrs[i];
+ String keySpecStr = keySpecStrs[i];
+
+ // generate the private key.
+ PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
+ Base64.getMimeDecoder().decode(keySpecStr));
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+ DSAPrivateKey priKey =
+ (DSAPrivateKey)kf.generatePrivate(priKeySpec);
+
+ // generate certificate chain
+ is = new ByteArrayInputStream(keyCertStr.getBytes());
+ Certificate keyCert = cf.generateCertificate(is);
+ is.close();
+
+ Certificate[] chain = null;
+ if (trusedCert != null) {
+ chain = new Certificate[2];
+ chain[0] = keyCert;
+ chain[1] = trusedCert;
+ } else {
+ chain = new Certificate[1];
+ chain[0] = keyCert;
+ }
+
+ // import the key entry.
+ ks.setKeyEntry("DSA Entry " + i, priKey, passphrase, chain);
+ }
+ }
+
+ // create SSL context
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm);
+ tmf.init(ks);
+
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ if (keyCertStrs != null && keyCertStrs.length != 0) {
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+ kmf.init(ks, passphrase);
+
+ ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ ks = null;
+ } else {
+ ctx.init(null, tmf.getTrustManagers(), null);
+ }
+
+ return ctx;
+ }
+
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ /*
+ * debug option
+ */
+ if (debug) {
+ System.setProperty("javax.net.debug", "all");
+ }
+
+ /*
+ * Get the customized arguments.
+ */
+ parseArguments(args);
+
+
+ /*
+ * Ignore testing on Windows if only SHA-224 is available.
+ */
+ if ((Security.getProvider("SunMSCAPI") != null) &&
+ (disabledAlgorithms.contains("SHA-1")) &&
+ (disabledAlgorithms.contains("SHA-256"))) {
+
+ System.out.println(
+ "Windows system does not support SHA-224 algorithms yet. " +
+ "Ignore the testing");
+
+ return;
+ }
+
+ /*
+ * Expose the target algorithms by diabling unexpected algorithms.
+ */
+ Security.setProperty(
+ "jdk.certpath.disabledAlgorithms", disabledAlgorithms);
+
+ /*
+ * Reset the security property to make sure that the algorithms
+ * and keys used in this test are not disabled by default.
+ */
+ Security.setProperty( "jdk.tls.disabledAlgorithms", "");
+
+ /*
+ * Start the tests.
+ */
+ new SignatureAlgorithms();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ SignatureAlgorithms() throws Exception {
+ try {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+ } catch (Exception e) {
+ // swallow for now. Show later
+ }
+
+ /*
+ * 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;
+
+ 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;
+ }
+ }
+
+ 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..." + e);
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ 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..." + e);
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ clientException = e;
+ }
+ }
+ }
+}
--- a/jdk/test/javax/net/ssl/templates/SSLExplorer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/net/ssl/templates/SSLExplorer.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,8 +29,6 @@
import javax.net.ssl.*;
import java.util.*;
-import sun.misc.HexDumpEncoder;
-
/**
* Instances of this class acts as an explorer of the network data of an
* SSL/TLS connection.
--- a/jdk/test/javax/print/PrintSEUmlauts/PrintSEUmlauts.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/print/PrintSEUmlauts/PrintSEUmlauts.java Wed Jan 06 14:54:24 2016 +0000
@@ -107,14 +107,14 @@
System.err.println("printing content");
System.err.println(content);
}
- throw new RuntimeException("Expected <e4> to represent 'ä' but not found!");
+ throw new RuntimeException("Expected <e4> to represent '\u00e4' but not found!");
}
System.err.println("SUCCESS");
}
public int print(Graphics g, PageFormat pf, int pg) {
if (pg > 0) return NO_SUCH_PAGE;
- g.drawString("ä", 100, 100);
+ g.drawString("\u00e4", 100, 100);
return PAGE_EXISTS;
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/print/attribute/Services_getDocFl.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,84 @@
+/*
+ * 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 javax.print.DocFlavor;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+
+/*
+ * @test
+ * @bug 4901243 8040139
+ * @summary JPG, GIF, and PNG DocFlavors (URL) should be supported if Postscript is supported.
+ * @run main Services_getDocFl
+*/
+
+
+public class Services_getDocFl {
+ public static void main (String [] args) {
+
+ HashPrintRequestAttributeSet prSet = null;
+ boolean psSupported = false,
+ pngImagesSupported = false,
+ gifImagesSupported = false,
+ jpgImagesSupported = false;
+ String mimeType;
+
+ PrintService[] serv = PrintServiceLookup.lookupPrintServices(null, null);
+ if (serv.length==0) {
+ System.out.println("no PrintService found");
+ } else {
+ System.out.println("number of Services "+serv.length);
+ }
+
+
+ for (int i = 0; i<serv.length ;i++) {
+ System.out.println(" PRINT SERVICE: "+ i+" "+serv[i]);
+ DocFlavor[] flavors = serv[i].getSupportedDocFlavors();
+ pngImagesSupported = false;
+ gifImagesSupported = false;
+ jpgImagesSupported = false;
+ for (int j=0; j<flavors.length; j++) {
+ System.out.println(flavors[j]);
+
+ if (flavors[j].equals(DocFlavor.URL.PNG)) {
+ pngImagesSupported = true;
+ } else if (flavors[j].equals(DocFlavor.URL.GIF)) {
+ gifImagesSupported = true;
+ } else if (flavors[j].equals(DocFlavor.URL.JPEG)) {
+ jpgImagesSupported = true;
+ } else if (flavors[j].getMimeType().indexOf("postscript") != -1) {
+ psSupported = true;
+ }
+ }
+
+ if (psSupported && !(pngImagesSupported && gifImagesSupported &&
+ jpgImagesSupported)) {
+
+ throw new RuntimeException("Error: URL image DocFlavors are not reported as supported");
+ }
+ }
+
+ }
+}
+
--- a/jdk/test/javax/security/auth/Subject/Subject.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/security/auth/Subject/Subject.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,6 @@
*/
package jjjjj.security.auth;
-import sun.misc.HexDumpEncoder;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.security.auth.x500.X500Principal;
@@ -107,7 +106,6 @@
public static byte[] enc(Object obj) {
try {
- HexDumpEncoder hex = new HexDumpEncoder();
ByteArrayOutputStream bout;
bout = new ByteArrayOutputStream();
new ObjectOutputStream(bout).writeObject(obj);
--- a/jdk/test/javax/sound/midi/MidiDeviceProvider/FakeInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +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.util.Collection;
-import java.util.HashSet;
-
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiDevice.Info;
-import javax.sound.midi.MidiSystem;
-import javax.sound.midi.MidiUnavailableException;
-import javax.sound.midi.spi.MidiDeviceProvider;
-
-import static java.util.ServiceLoader.load;
-
-/**
- * @test
- * @bug 8059743
- * @summary MidiDeviceProvider shouldn't returns incorrect results in case of
- * some unknown MidiDevice.Info
- * @author Sergey Bylokhov
- */
-public final class FakeInfo {
-
- private static final class Fake extends Info {
-
- Fake() {
- super("a", "b", "c", "d");
- }
- }
-
- public static void main(final String[] args) {
- final Info fake = new Fake();
- // MidiSystem API
- try {
- MidiSystem.getMidiDevice(fake);
- throw new RuntimeException("IllegalArgumentException expected");
- } catch (final MidiUnavailableException e) {
- throw new RuntimeException("IllegalArgumentException expected", e);
- } catch (final IllegalArgumentException ignored) {
- // expected
- }
- // MidiDeviceProvider API
- final Collection<String> errors = new HashSet<>();
- for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
- try {
- if (mdp.isDeviceSupported(fake)) {
- throw new RuntimeException("fake is supported");
- }
- final MidiDevice device = mdp.getDevice(fake);
- System.err.println("MidiDevice: " + device);
- throw new RuntimeException("IllegalArgumentException expected");
- } catch (final IllegalArgumentException e) {
- errors.add(e.getMessage());
- }
- }
- if (errors.size() != 1) {
- throw new RuntimeException("Wrong number of messages:" + errors);
- }
- }
-}
--- a/jdk/test/javax/sound/midi/MidiDeviceProvider/NullInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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.
- */
-
-import java.util.Collection;
-import java.util.HashSet;
-
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiSystem;
-import javax.sound.midi.MidiUnavailableException;
-import javax.sound.midi.spi.MidiDeviceProvider;
-
-import static java.util.ServiceLoader.load;
-
-/**
- * @test
- * @bug 8058115
- * @summary MidiDeviceProvider shouldn't returns incorrect results or throw NPE
- * in case of null MidiDevice.Info
- * @author Sergey Bylokhov
- */
-public final class NullInfo {
-
- public static void main(final String[] args) {
- // MidiSystem API
- try {
- MidiSystem.getMidiDevice(null);
- throw new RuntimeException("IllegalArgumentException expected");
- } catch (final MidiUnavailableException e) {
- throw new RuntimeException("IllegalArgumentException expected", e);
- } catch (final IllegalArgumentException ignored) {
- // expected
- }
- // MidiDeviceProvider API
- final Collection<String> errors = new HashSet<>();
- for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
- try {
- if (mdp.isDeviceSupported(null)) {
- throw new RuntimeException("null is supported");
- }
- final MidiDevice device = mdp.getDevice(null);
- System.err.println("MidiDevice: " + device);
- throw new RuntimeException("IllegalArgumentException expected");
- } catch (final IllegalArgumentException e) {
- errors.add(e.getMessage());
- }
- }
- if (errors.size() != 1) {
- throw new RuntimeException("Wrong number of messages:" + errors);
- }
- }
-}
--- a/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * 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.
- */
-
-import javax.sound.midi.MidiDevice;
-import javax.sound.midi.MidiSystem;
-import javax.sound.midi.spi.MidiDeviceProvider;
-
-import static java.util.ServiceLoader.load;
-
-/**
- * @test
- * @bug 8058115
- * @summary MidiDeviceProvider shouldn't returns incorrect results in case of
- * unsupported MidiDevice.Info
- * @author Sergey Bylokhov
- */
-public final class UnsupportedInfo {
-
- public static void main(final String[] args) {
- final MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
- for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
- for (final MidiDevice.Info info : infos) {
- if (mdp.isDeviceSupported(info)) {
- if (mdp.getDevice(info) == null) {
- throw new RuntimeException("MidiDevice is null");
- }
- } else {
- try {
- mdp.getDevice(info);
- throw new RuntimeException(
- "IllegalArgumentException expected");
- } catch (final IllegalArgumentException ignored) {
- // expected
- }
- }
- }
- }
- }
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/MidiDeviceProvider/ExpectedNPEOnNull.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,94 @@
+/*
+ * 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.util.Objects;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8143909
+ * @author Sergey Bylokhov
+ */
+public final class ExpectedNPEOnNull {
+
+ public static void main(final String[] args) throws Exception {
+ testMS();
+ for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
+ testMDP(mdp);
+ }
+ testMDP(customMDP);
+ }
+
+ /**
+ * Tests the part of MidiSystem API, which implemented via
+ * MidiDeviceProvider.
+ */
+ private static void testMS() throws Exception {
+ // MidiSystem#getMidiDevice(MidiDevice.Info)
+ try {
+ MidiSystem.getMidiDevice(null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+
+ /**
+ * Tests the MidiDeviceProvider API directly.
+ */
+ private static void testMDP(final MidiDeviceProvider mdp) throws Exception {
+ // MidiDeviceProvider#isDeviceSupported(Info)
+ try {
+ mdp.isDeviceSupported(null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiDeviceProvider#getDevice(Info)
+ try {
+ mdp.getDevice(null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+
+ /**
+ * Tests some default implementation of MidiDeviceProvider API, using the
+ * custom {@code MidiDeviceProvider}, which support nothing.
+ */
+ static MidiDeviceProvider customMDP = new MidiDeviceProvider() {
+ @Override
+ public MidiDevice.Info[] getDeviceInfo() {
+ return new MidiDevice.Info[0];
+ }
+
+ @Override
+ public MidiDevice getDevice(MidiDevice.Info info) {
+ Objects.requireNonNull(info);
+ return null;
+ }
+ };
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/MidiDeviceProvider/FakeInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,80 @@
+/*
+ * 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.util.Collection;
+import java.util.HashSet;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiDevice.Info;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8059743
+ * @summary MidiDeviceProvider shouldn't returns incorrect results in case of
+ * some unknown MidiDevice.Info
+ * @author Sergey Bylokhov
+ */
+public final class FakeInfo {
+
+ private static final class Fake extends Info {
+
+ Fake() {
+ super("a", "b", "c", "d");
+ }
+ }
+
+ public static void main(final String[] args) {
+ final Info fake = new Fake();
+ // MidiSystem API
+ try {
+ MidiSystem.getMidiDevice(fake);
+ throw new RuntimeException("IllegalArgumentException expected");
+ } catch (final MidiUnavailableException e) {
+ throw new RuntimeException("IllegalArgumentException expected", e);
+ } catch (final IllegalArgumentException ignored) {
+ // expected
+ }
+ // MidiDeviceProvider API
+ final Collection<String> errors = new HashSet<>();
+ for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
+ try {
+ if (mdp.isDeviceSupported(fake)) {
+ throw new RuntimeException("fake is supported");
+ }
+ final MidiDevice device = mdp.getDevice(fake);
+ System.err.println("MidiDevice: " + device);
+ throw new RuntimeException("IllegalArgumentException expected");
+ } catch (final IllegalArgumentException e) {
+ errors.add(e.getMessage());
+ }
+ }
+ if (errors.size() != 1) {
+ throw new RuntimeException("Wrong number of messages:" + errors);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/MidiDeviceProvider/UnsupportedInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8058115
+ * @summary MidiDeviceProvider shouldn't returns incorrect results in case of
+ * unsupported MidiDevice.Info
+ * @author Sergey Bylokhov
+ */
+public final class UnsupportedInfo {
+
+ public static void main(final String[] args) {
+ final MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+ for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) {
+ for (final MidiDevice.Info info : infos) {
+ if (mdp.isDeviceSupported(info)) {
+ if (mdp.getDevice(info) == null) {
+ throw new RuntimeException("MidiDevice is null");
+ }
+ } else {
+ try {
+ mdp.getDevice(info);
+ throw new RuntimeException(
+ "IllegalArgumentException expected");
+ } catch (final IllegalArgumentException ignored) {
+ // expected
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/MidiFileReader/ExpectedNPEOnNull.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,130 @@
+/*
+ * 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.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.spi.MidiFileReader;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8143909
+ * @author Sergey Bylokhov
+ */
+public final class ExpectedNPEOnNull {
+
+ public static void main(final String[] args) throws Exception {
+ testMS();
+ for (final MidiFileReader mfr : load(MidiFileReader.class)) {
+ testMFR(mfr);
+ }
+ }
+
+ /**
+ * Tests the part of MidiSystem API, which implemented via MidiFileReader.
+ */
+ private static void testMS() throws Exception {
+ // MidiSystem#getMidiFileFormat(InputStream)
+ try {
+ MidiSystem.getMidiFileFormat((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getMidiFileFormat(URL)
+ try {
+ MidiSystem.getMidiFileFormat((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getMidiFileFormat(File)
+ try {
+ MidiSystem.getMidiFileFormat((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getSequence(InputStream)
+ try {
+ MidiSystem.getSequence((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getSequence(URL)
+ try {
+ MidiSystem.getSequence((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getSequence(File)
+ try {
+ MidiSystem.getSequence((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+
+ /**
+ * Tests the MidiFileReader API directly.
+ */
+ private static void testMFR(final MidiFileReader mfr) throws Exception {
+ // MidiFileReader#getMidiFileFormat(InputStream)
+ try {
+ mfr.getMidiFileFormat((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileReader#getMidiFileFormat(URL)
+ try {
+ mfr.getMidiFileFormat((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileReader#getMidiFileFormat(File)
+ try {
+ mfr.getMidiFileFormat((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileReader#getSequence(InputStream)
+ try {
+ mfr.getSequence((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileReader#getSequence(URL)
+ try {
+ mfr.getSequence((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileReader#getSequence(File)
+ try {
+ mfr.getSequence((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/MidiFileWriter/ExpectedNPEOnNull.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,215 @@
+/*
+ * 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.io.File;
+import java.io.OutputStream;
+import java.util.Objects;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.spi.MidiFileWriter;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8143909
+ * @author Sergey Bylokhov
+ */
+public final class ExpectedNPEOnNull {
+
+ public static void main(final String[] args) throws Exception {
+ testMS();
+ for (final MidiFileWriter mfw : load(MidiFileWriter.class)) {
+ testMFW(mfw);
+ }
+ testMFW(customMFW);
+ }
+
+ /**
+ * Tests the part of MidiSystem API, which implemented via MidiFileWriter.
+ */
+ private static void testMS() throws Exception {
+ // MidiSystem#getMidiFileTypes(Sequence)
+ try {
+ MidiSystem.getMidiFileTypes(null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+
+ // MidiSystem#isFileTypeSupported(int, Sequence)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.isFileTypeSupported(type, null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ // MidiSystem#write(Sequence, int, OutputStream)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(null, type, new NullOutputStream());
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(new Sequence(0, 0), type, (OutputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(null, type, (OutputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ // MidiSystem#write(Sequence, int, File)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(null, type, new File(""));
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(new Sequence(0, 0), type, (File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ MidiSystem.write(null, type, (File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Tests the MidiFileWriter API directly.
+ */
+ private static void testMFW(final MidiFileWriter mfw) throws Exception {
+ // MidiFileWriter#getMidiFileTypes(Sequence)
+ try {
+ mfw.getMidiFileTypes(null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiFileWriter#isFileTypeSupported(int, Sequence)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.isFileTypeSupported(type, null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ // MidiFileWriter#write(Sequence, int, OutputStream)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(null, type, new NullOutputStream());
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(new Sequence(0, 0), type, (OutputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(null, type, (OutputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ // MidiFileWriter#write(Sequence, int, File)
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(null, type, new File(""));
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(new Sequence(0, 0), type, (File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ for (final int type : MidiSystem.getMidiFileTypes()) {
+ try {
+ mfw.write(null, type, (File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+ }
+ /**
+ * Tests some default implementation of MidiFileWriter API, using the custom
+ * {@code MidiFileWriter}, which support nothing.
+ */
+ static MidiFileWriter customMFW = new MidiFileWriter() {
+ @Override
+ public int[] getMidiFileTypes() {
+ return new int[0];
+ }
+
+ @Override
+ public int[] getMidiFileTypes(Sequence sequence) {
+ Objects.requireNonNull(sequence);
+ return new int[0];
+ }
+
+ @Override
+ public int write(Sequence in, int fileType, OutputStream out) {
+ Objects.requireNonNull(in);
+ Objects.requireNonNull(out);
+ return 0;
+ }
+
+ @Override
+ public int write(Sequence in, int fileType, File out) {
+ Objects.requireNonNull(in);
+ Objects.requireNonNull(out);
+ return 0;
+ }
+ };
+
+ private static final class NullOutputStream extends OutputStream {
+
+ @Override
+ public void write(final int b) {
+ //do nothing
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/spi/SoundbankReader/ExpectedNPEOnNull.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,94 @@
+/*
+ * 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.io.File;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.spi.SoundbankReader;
+
+import static java.util.ServiceLoader.load;
+
+/**
+ * @test
+ * @bug 8143909
+ * @author Sergey Bylokhov
+ */
+public final class ExpectedNPEOnNull {
+
+ public static void main(final String[] args) throws Exception {
+ testMS();
+ for (final SoundbankReader sbr : load(SoundbankReader.class)) {
+ testSBR(sbr);
+ }
+ }
+
+ /**
+ * Tests the part of MidiSystem API, which implemented via SoundbankReader.
+ */
+ private static void testMS() throws Exception {
+ // MidiSystem#getSoundbank(InputStream)
+ try {
+ MidiSystem.getSoundbank((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getSoundbank(URL)
+ try {
+ MidiSystem.getSoundbank((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // MidiSystem#getSoundbank(File)
+ try {
+ MidiSystem.getSoundbank((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+
+ /**
+ * Tests the SoundbankReader API directly.
+ */
+ private static void testSBR(final SoundbankReader sbr) throws Exception {
+ // SoundbankReader#getSoundbank(InputStream)
+ try {
+ sbr.getSoundbank((InputStream) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // SoundbankReader#getSoundbank(URL)
+ try {
+ sbr.getSoundbank((URL) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ // SoundbankReader#getSoundbank(File)
+ try {
+ sbr.getSoundbank((File) null);
+ throw new RuntimeException("NPE is expected");
+ } catch (final NullPointerException ignored) {
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/8067660/FileChooserTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8067660
+ * @summary JFileChooser create new folder fails silently
+ * @requires (os.family == "windows")
+ * @run main/manual FileChooserTest
+ */
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+public class FileChooserTest {
+
+ private static boolean theTestPassed;
+ private static boolean testGeneratedInterrupt;
+ private static Thread mainThread;
+ private static int sleepTime = 30000;
+ public static JFileChooser fileChooser;
+
+ private static void init() throws Exception {
+
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ String[] instructions
+ = {
+ "1) Create a folder with read only permissions",
+ "2) Click on run test button.It will open a open dialog"
+ + " Navigate to the newly created read only folder",
+ "3) Click on the create new folder button in open dialog",
+ "4) If an error message does not pops up"
+ + "test failed otherwise passed.",
+ "5) Pressing Pass/Fail button will mark test as "
+ + "pass/fail and will shutdown JVM"};
+
+ Sysout.createDialogWithInstructions(instructions);
+ Sysout.printInstructions(instructions);
+ }
+ });
+ }
+
+ /**
+ * ***************************************************
+ * Standard Test Machinery Section DO NOT modify anything in this section --
+ * it's a standard chunk of code which has all of the synchronisation
+ * necessary for the test harness. By keeping it the same in all tests, it
+ * is easier to read and understand someone else's test, as well as insuring
+ * that all tests behave correctly with the test harness. There is a section
+ * following this for test-defined classes
+ */
+ public static void main(String args[]) throws Exception {
+
+ mainThread = Thread.currentThread();
+ try {
+ init();
+ } catch (Exception ex) {
+ return;
+ }
+ try {
+ mainThread.sleep(sleepTime);
+ } catch (InterruptedException ex) {
+ Sysout.dispose();
+ if (!theTestPassed && testGeneratedInterrupt) {
+ throw new RuntimeException("Test Failed");
+ }
+ }
+ if (!testGeneratedInterrupt) {
+ Sysout.dispose();
+ throw new RuntimeException("Test Failed");
+ }
+ }
+
+ public static synchronized void pass() {
+ theTestPassed = true;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+
+ public static synchronized void fail() {
+ theTestPassed = false;
+ testGeneratedInterrupt = true;
+ mainThread.interrupt();
+ }
+}
+
+/**
+ * This is part of the standard test machinery. It creates a dialog (with the
+ * instructions), and is the interface for sending text messages to the user. To
+ * print the instructions, send an array of strings to Sysout.createDialog
+ * WithInstructions method. Put one line of instructions per array entry. To
+ * display a message for the tester to see, simply call Sysout.println with the
+ * string to be displayed. This mimics System.out.println but works within the
+ * test harness as well as standalone.
+ */
+class Sysout {
+
+ private static TestDialog dialog;
+ private static JFrame frame;
+
+ public static void createDialogWithInstructions(String[] instructions) {
+ frame = new JFrame();
+ dialog = new TestDialog(frame, "Instructions");
+ dialog.printInstructions(instructions);
+ dialog.setVisible(true);
+ println("Any messages for the tester will display here.");
+ }
+
+ public static void printInstructions(String[] instructions) {
+ dialog.printInstructions(instructions);
+ }
+
+ public static void println(String messageIn) {
+ dialog.displayMessage(messageIn);
+ }
+
+ public static void dispose() {
+ Sysout.println("Shutting down the Java process..");
+ if(FileChooserTest.fileChooser != null) {
+ FileChooserTest.fileChooser.cancelSelection();
+ }
+ frame.dispose();
+ dialog.dispose();
+ }
+}
+
+/**
+ * This is part of the standard test machinery. It provides a place for the test
+ * instructions to be displayed, and a place for interactive messages to the
+ * user to be displayed. To have the test instructions displayed, see Sysout. To
+ * have a message to the user be displayed, see Sysout. Do not call anything in
+ * this dialog directly.
+ */
+class TestDialog extends JDialog {
+
+ private TextArea instructionsText;
+ private TextArea messageText;
+ private int maxStringLength = 80;
+ private Panel buttonP = new Panel();
+ private JButton run = new JButton("Run");
+ private JButton passB = new JButton("Pass");
+ private JButton failB = new JButton("Fail");
+
+ public TestDialog(JFrame frame, String name) {
+ super(frame, name);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ int scrollBoth = TextArea.SCROLLBARS_BOTH;
+ instructionsText = new TextArea("", 15, maxStringLength, scrollBoth);
+ add("North", instructionsText);
+
+ messageText = new TextArea("", 5, maxStringLength, scrollBoth);
+ add("Center", messageText);
+
+ buttonP.add("East", run);
+ buttonP.add("East", passB);
+ buttonP.add("West", failB);
+ passB.setEnabled(false);
+ failB.setEnabled(false);
+ add("South", buttonP);
+
+ run.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ FileChooserTest.fileChooser = new JFileChooser();
+ FileChooserTest.fileChooser.showOpenDialog(null);
+ passB.setEnabled(true);
+ failB.setEnabled(true);
+ }
+ });
+
+ passB.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ FileChooserTest.pass();
+ }
+ });
+
+ failB.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent ae) {
+ FileChooserTest.fail();
+ }
+ });
+ pack();
+
+ setVisible(true);
+ }
+
+ public void printInstructions(String[] instructions) {
+ instructionsText.setText("");
+
+ String printStr, remainingStr;
+ for (String instruction : instructions) {
+ remainingStr = instruction;
+ while (remainingStr.length() > 0) {
+ if (remainingStr.length() >= maxStringLength) {
+ int posOfSpace = remainingStr.
+ lastIndexOf(' ', maxStringLength - 1);
+
+ if (posOfSpace <= 0) {
+ posOfSpace = maxStringLength - 1;
+ }
+
+ printStr = remainingStr.substring(0, posOfSpace + 1);
+ remainingStr = remainingStr.substring(posOfSpace + 1);
+ } else {
+ printStr = remainingStr;
+ remainingStr = "";
+ }
+ instructionsText.append(printStr + "\n");
+ }
+ }
+
+ }
+
+ public void displayMessage(String messageIn) {
+ messageText.append(messageIn + "\n");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JMenuItem/8139169/ScreenMenuBarInputTwice.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,234 @@
+/*
+ * 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.
+ */
+
+/* @test
+ * @bug 8139169
+ * @summary verifies if TextArea gets input twice due to Apple's Screen Menubar
+ * @requires (os.family=="mac")
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main ScreenMenuBarInputTwice
+ */
+import java.awt.BorderLayout;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import static java.awt.event.KeyEvent.VK_COMMA;
+import static java.awt.event.KeyEvent.VK_META;
+import static java.awt.event.KeyEvent.VK_SHIFT;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.text.BadLocationException;
+
+public class ScreenMenuBarInputTwice {
+
+ public static final String TEST_STRING = "Check string";
+
+ private static Robot robot;
+ private static JFrame frame;
+ private static JPanel content;
+ private static JTextArea textArea;
+ private static JMenuBar menuBar;
+ private static JMenu menu;
+ private static JMenuItem menuItem;
+
+ public static void main(String[] args) throws Exception {
+ robot = new Robot();
+ createUIWithSeperateMenuBar();
+ robot.delay(2000);
+ shortcutTestCase();
+ robot.delay(2000);
+ cleanUp();
+ createUIWithIntegratedMenuBar();
+ robot.delay(2000);
+ menuTestCase();
+ robot.delay(2000);
+ cleanUp();
+ }
+
+ private static void createUIWithSeperateMenuBar() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ System.setProperty(
+ "com.apple.mrj.application.apple.menu.about.name",
+ "A test frame");
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+ frame = new JFrame("Text input twice check");
+ content = new JPanel(new BorderLayout());
+ textArea = new JTextArea();
+ content.add(new JScrollPane(textArea,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
+ BorderLayout.CENTER);
+ menuBar = new JMenuBar();
+ frame.setJMenuBar(menuBar);
+ Action a = new AbstractAction("Insert some text") {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+
+ textArea.getDocument()
+ .insertString(0, TEST_STRING, null);
+ } catch (BadLocationException e) {
+ frame.dispose();
+ throw new RuntimeException("Bad location: ", e);
+ }
+ }
+ };
+ KeyStroke keyStroke = KeyStroke.getKeyStroke(
+ "meta shift COMMA");
+ a.putValue(Action.ACCELERATOR_KEY, keyStroke);
+ textArea.getInputMap().put(keyStroke, "myAction");
+ textArea.getActionMap().put("myAction", a);
+ menu = new JMenu("The Menu");
+ menuItem = new JMenuItem(a);
+ menuItem.setAccelerator((KeyStroke) a.getValue(
+ Action.ACCELERATOR_KEY));
+ menu.add(menuItem);
+ menuBar.add(menu);
+ frame.getContentPane().add(content);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setLocationRelativeTo(null);
+ frame.setSize(500, 500);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+ });
+ }
+
+ private static void createUIWithIntegratedMenuBar() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ System.setProperty(
+ "com.apple.mrj.application.apple.menu.about.name",
+ "A test frame");
+ System.setProperty("apple.laf.useScreenMenuBar", "false");
+ frame = new JFrame("Text input twice check");
+ content = new JPanel(new BorderLayout());
+ textArea = new JTextArea();
+ content.add(new JScrollPane(textArea,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED),
+ BorderLayout.CENTER);
+ menuBar = new JMenuBar();
+ frame.setJMenuBar(menuBar);
+ Action a = new AbstractAction("Insert some text") {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ try {
+
+ textArea.getDocument()
+ .insertString(0, TEST_STRING, null);
+ } catch (BadLocationException e) {
+ frame.dispose();
+ throw new RuntimeException("Bad location: ", e);
+ }
+ }
+ };
+ KeyStroke keyStroke = KeyStroke.getKeyStroke(
+ "meta shift COMMA");
+ a.putValue(Action.ACCELERATOR_KEY, keyStroke);
+ textArea.getInputMap().put(keyStroke, "myAction");
+ textArea.getActionMap().put("myAction", a);
+ menu = new JMenu("The Menu");
+ menuItem = new JMenuItem(a);
+ menuItem.setAccelerator((KeyStroke) a.getValue(
+ Action.ACCELERATOR_KEY));
+ menu.add(menuItem);
+ menuBar.add(menu);
+ frame.getContentPane().add(content);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(500, 500);
+ frame.setLocationRelativeTo(null);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+ });
+ }
+
+ private static void shortcutTestCase() throws Exception {
+ robot.keyPress(KeyEvent.VK_META);
+ robot.keyPress(KeyEvent.VK_SHIFT);
+ robot.keyPress(KeyEvent.VK_COMMA);
+ robot.keyRelease(VK_COMMA);
+ robot.keyRelease(VK_SHIFT);
+ robot.keyRelease(VK_META);
+ robot.delay(2000);
+ checkText(textArea.getText());
+ }
+
+ private static void menuTestCase() throws Exception {
+ Point mousePoint;
+ mousePoint = Util.getCenterPoint(menu);
+ robot.mouseMove(mousePoint.x, mousePoint.y);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.delay(2000);
+ mousePoint = Util.getCenterPoint(menuItem);
+ robot.mouseMove(mousePoint.x, mousePoint.y);
+ robot.delay(2000);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.mouseRelease(InputEvent.BUTTON1_MASK);
+ robot.delay(2000);
+ checkText(textArea.getText());
+ }
+
+ private static void checkText(String text) throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ if (TEST_STRING.equals(text)) {
+ textArea.setText("");
+ } else {
+ frame.dispose();
+ throw new RuntimeException("Failed. "
+ + " Menu item shortcut invoked twice");
+ }
+ }
+ });
+ }
+
+ private static void cleanUp() throws Exception {
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ frame.dispose();
+ }
+ });
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+/* @test
+ @bug 8030702
+ @summary Deadlock between subclass of AbstractDocument and UndoManager
+ @author Semyon Sadetsky
+ */
+
+import javax.swing.text.PlainDocument;
+import javax.swing.text.StringContent;
+import javax.swing.undo.UndoManager;
+import java.text.DecimalFormat;
+import java.text.Format;
+import java.util.concurrent.CyclicBarrier;
+
+public class AbstractDocumentUndoConcurrentTest {
+ static CyclicBarrier barrier = new CyclicBarrier(3);
+
+ private static PlainDocument doc1;
+ private static PlainDocument doc2;
+ private static Format format1 = new DecimalFormat("<Test1 0000>");
+ private static Format format2 = new DecimalFormat("<Test22 0000>");
+
+ public static void main(String[] args) throws Exception {
+ test();
+ System.out.println(doc1.getText(0, doc1.getLength()));
+ System.out.println(doc2.getText(0, doc2.getLength()));
+ System.out.println("ok");
+ }
+
+ private static void test() throws Exception {
+ doc1 = new PlainDocument(new StringContent());
+ final UndoManager undoManager = new UndoManager();
+
+ doc1.addUndoableEditListener(undoManager);
+ doc1.insertString(0, "<Test1 XXXX>", null);
+
+ doc2 = new PlainDocument(new StringContent());
+
+ doc2.addUndoableEditListener(undoManager);
+ doc2.insertString(0, "<Test22 XXXX>", null);
+
+ Thread t1 = new Thread("Thread doc1") {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ for (int i = 0; i < 1000; i++) {
+ doc1.insertString(0, format1.format(i), null);
+ if(doc1.getLength() > 100) doc1.remove(0, 12);
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("t1 done");
+ }
+ };
+
+ Thread t2 = new Thread("Thread doc2") {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ for (int i = 0; i < 1000; i++) {
+ doc2.insertString(0, format2.format(i), null);
+ if(doc2.getLength() > 100) doc2.remove(0, 13);
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ System.out.println("t2 done");
+ }
+ };
+
+ Thread t3 = new Thread("Undo/Redo Thread") {
+ @Override
+ public void run() {
+ try {
+ barrier.await();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ for (int i = 0; i < 1000; i++) {
+ undoManager.undoOrRedo();
+ undoManager.undo();
+ }
+ System.out.println("t3 done");
+ }
+ };
+
+ t1.start();
+ t2.start();
+ t3.start();
+
+ t1.join();
+ t2.join();
+ t3.join();
+ }
+}
--- a/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/javax/xml/crypto/dsig/SecurityManager/XMLDSigWithSecMgr.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -33,8 +33,6 @@
import java.net.*;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
-import java.security.Policy;
-import java.security.URIParameter;
import java.util.ArrayList;
import java.util.Collections;
import javax.xml.crypto.dsig.*;
@@ -115,10 +113,8 @@
// the policy only grants this test SocketPermission to accept, resolve
// and connect to localhost so that it can dereference 2nd reference
- URI policyURI =
- new File(System.getProperty("test.src", "."), "policy").toURI();
- Policy.setPolicy
- (Policy.getInstance("JavaPolicy", new URIParameter(policyURI)));
+ System.setProperty("java.security.policy",
+ System.getProperty("test.src", ".") + File.separator + "policy");
System.setSecurityManager(new SecurityManager());
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/OldFDBigIntForTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//package jdk.internal.math;
+
+/*
+ * A really, really simple bigint package
+ * tailored to the needs of floating base conversion.
+ */
+class OldFDBigIntForTest {
+ int nWords; // number of words used
+ int data[]; // value: data[0] is least significant
+
+
+ public OldFDBigIntForTest( int v ){
+ nWords = 1;
+ data = new int[1];
+ data[0] = v;
+ }
+
+ public OldFDBigIntForTest( long v ){
+ data = new int[2];
+ data[0] = (int)v;
+ data[1] = (int)(v>>>32);
+ nWords = (data[1]==0) ? 1 : 2;
+ }
+
+ public OldFDBigIntForTest( OldFDBigIntForTest other ){
+ data = new int[nWords = other.nWords];
+ System.arraycopy( other.data, 0, data, 0, nWords );
+ }
+
+ private OldFDBigIntForTest( int [] d, int n ){
+ data = d;
+ nWords = n;
+ }
+
+ public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
+ int n= (nd+8)/9; // estimate size needed.
+ if ( n < 2 ) n = 2;
+ data = new int[n]; // allocate enough space
+ data[0] = (int)seed; // starting value
+ data[1] = (int)(seed>>>32);
+ nWords = (data[1]==0) ? 1 : 2;
+ int i = nd0;
+ int limit = nd-5; // slurp digits 5 at a time.
+ int v;
+ while ( i < limit ){
+ int ilim = i+5;
+ v = (int)digit[i++]-(int)'0';
+ while( i <ilim ){
+ v = 10*v + (int)digit[i++]-(int)'0';
+ }
+ multaddMe( 100000, v); // ... where 100000 is 10^5.
+ }
+ int factor = 1;
+ v = 0;
+ while ( i < nd ){
+ v = 10*v + (int)digit[i++]-(int)'0';
+ factor *= 10;
+ }
+ if ( factor != 1 ){
+ multaddMe( factor, v );
+ }
+ }
+
+ /*
+ * Left shift by c bits.
+ * Shifts this in place.
+ */
+ public void
+ lshiftMe( int c )throws IllegalArgumentException {
+ if ( c <= 0 ){
+ if ( c == 0 )
+ return; // silly.
+ else
+ throw new IllegalArgumentException("negative shift count");
+ }
+ int wordcount = c>>5;
+ int bitcount = c & 0x1f;
+ int anticount = 32-bitcount;
+ int t[] = data;
+ int s[] = data;
+ if ( nWords+wordcount+1 > t.length ){
+ // reallocate.
+ t = new int[ nWords+wordcount+1 ];
+ }
+ int target = nWords+wordcount;
+ int src = nWords-1;
+ if ( bitcount == 0 ){
+ // special hack, since an anticount of 32 won't go!
+ System.arraycopy( s, 0, t, wordcount, nWords );
+ target = wordcount-1;
+ } else {
+ t[target--] = s[src]>>>anticount;
+ while ( src >= 1 ){
+ t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
+ }
+ t[target--] = s[src]<<bitcount;
+ }
+ while( target >= 0 ){
+ t[target--] = 0;
+ }
+ data = t;
+ nWords += wordcount + 1;
+ // may have constructed high-order word of 0.
+ // if so, trim it
+ while ( nWords > 1 && data[nWords-1] == 0 )
+ nWords--;
+ }
+
+ /*
+ * normalize this number by shifting until
+ * the MSB of the number is at 0x08000000.
+ * This is in preparation for quoRemIteration, below.
+ * The idea is that, to make division easier, we want the
+ * divisor to be "normalized" -- usually this means shifting
+ * the MSB into the high words sign bit. But because we know that
+ * the quotient will be 0 < q < 10, we would like to arrange that
+ * the dividend not span up into another word of precision.
+ * (This needs to be explained more clearly!)
+ */
+ public int
+ normalizeMe() throws IllegalArgumentException {
+ int src;
+ int wordcount = 0;
+ int bitcount = 0;
+ int v = 0;
+ for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
+ wordcount += 1;
+ }
+ if ( src < 0 ){
+ // oops. Value is zero. Cannot normalize it!
+ throw new IllegalArgumentException("zero value");
+ }
+ /*
+ * In most cases, we assume that wordcount is zero. This only
+ * makes sense, as we try not to maintain any high-order
+ * words full of zeros. In fact, if there are zeros, we will
+ * simply SHORTEN our number at this point. Watch closely...
+ */
+ nWords -= wordcount;
+ /*
+ * Compute how far left we have to shift v s.t. its highest-
+ * order bit is in the right place. Then call lshiftMe to
+ * do the work.
+ */
+ if ( (v & 0xf0000000) != 0 ){
+ // will have to shift up into the next word.
+ // too bad.
+ for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
+ v >>>= 1;
+ } else {
+ while ( v <= 0x000fffff ){
+ // hack: byte-at-a-time shifting
+ v <<= 8;
+ bitcount += 8;
+ }
+ while ( v <= 0x07ffffff ){
+ v <<= 1;
+ bitcount += 1;
+ }
+ }
+ if ( bitcount != 0 )
+ lshiftMe( bitcount );
+ return bitcount;
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by an int.
+ * Result is a new OldFDBigIntForTest.
+ */
+ public OldFDBigIntForTest
+ mult( int iv ) {
+ long v = iv;
+ int r[];
+ long p;
+
+ // guess adequate size of r.
+ r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
+ p = 0L;
+ for( int i=0; i < nWords; i++ ) {
+ p += v * ((long)data[i]&0xffffffffL);
+ r[i] = (int)p;
+ p >>>= 32;
+ }
+ if ( p == 0L){
+ return new OldFDBigIntForTest( r, nWords );
+ } else {
+ r[nWords] = (int)p;
+ return new OldFDBigIntForTest( r, nWords+1 );
+ }
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by an int and add another int.
+ * Result is computed in place.
+ * Hope it fits!
+ */
+ public void
+ multaddMe( int iv, int addend ) {
+ long v = iv;
+ long p;
+
+ // unroll 0th iteration, doing addition.
+ p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
+ data[0] = (int)p;
+ p >>>= 32;
+ for( int i=1; i < nWords; i++ ) {
+ p += v * ((long)data[i]&0xffffffffL);
+ data[i] = (int)p;
+ p >>>= 32;
+ }
+ if ( p != 0L){
+ data[nWords] = (int)p; // will fail noisily if illegal!
+ nWords++;
+ }
+ }
+
+ /*
+ * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
+ * Result is a new OldFDBigIntForTest.
+ */
+ public OldFDBigIntForTest
+ mult( OldFDBigIntForTest other ){
+ // crudely guess adequate size for r
+ int r[] = new int[ nWords + other.nWords ];
+ int i;
+ // I think I am promised zeros...
+
+ for( i = 0; i < this.nWords; i++ ){
+ long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
+ long p = 0L;
+ int j;
+ for( j = 0; j < other.nWords; j++ ){
+ p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
+ r[i+j] = (int)p;
+ p >>>= 32;
+ }
+ r[i+j] = (int)p;
+ }
+ // compute how much of r we actually needed for all that.
+ for ( i = r.length-1; i> 0; i--)
+ if ( r[i] != 0 )
+ break;
+ return new OldFDBigIntForTest( r, i+1 );
+ }
+
+ /*
+ * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
+ */
+ public OldFDBigIntForTest
+ add( OldFDBigIntForTest other ){
+ int i;
+ int a[], b[];
+ int n, m;
+ long c = 0L;
+ // arrange such that a.nWords >= b.nWords;
+ // n = a.nWords, m = b.nWords
+ if ( this.nWords >= other.nWords ){
+ a = this.data;
+ n = this.nWords;
+ b = other.data;
+ m = other.nWords;
+ } else {
+ a = other.data;
+ n = other.nWords;
+ b = this.data;
+ m = this.nWords;
+ }
+ int r[] = new int[ n ];
+ for ( i = 0; i < n; i++ ){
+ c += (long)a[i] & 0xffffffffL;
+ if ( i < m ){
+ c += (long)b[i] & 0xffffffffL;
+ }
+ r[i] = (int) c;
+ c >>= 32; // signed shift.
+ }
+ if ( c != 0L ){
+ // oops -- carry out -- need longer result.
+ int s[] = new int[ r.length+1 ];
+ System.arraycopy( r, 0, s, 0, r.length );
+ s[i++] = (int)c;
+ return new OldFDBigIntForTest( s, i );
+ }
+ return new OldFDBigIntForTest( r, i );
+ }
+
+ /*
+ * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
+ * Assert that the result is positive.
+ */
+ public OldFDBigIntForTest
+ sub( OldFDBigIntForTest other ){
+ int r[] = new int[ this.nWords ];
+ int i;
+ int n = this.nWords;
+ int m = other.nWords;
+ int nzeros = 0;
+ long c = 0L;
+ for ( i = 0; i < n; i++ ){
+ c += (long)this.data[i] & 0xffffffffL;
+ if ( i < m ){
+ c -= (long)other.data[i] & 0xffffffffL;
+ }
+ if ( ( r[i] = (int) c ) == 0 )
+ nzeros++;
+ else
+ nzeros = 0;
+ c >>= 32; // signed shift
+ }
+ assert c == 0L : c; // borrow out of subtract
+ assert dataInRangeIsZero(i, m, other); // negative result of subtract
+ return new OldFDBigIntForTest( r, n-nzeros );
+ }
+
+ private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
+ while ( i < m )
+ if (other.data[i++] != 0)
+ return false;
+ return true;
+ }
+
+ /*
+ * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
+ * >0: this > other
+ * 0: this == other
+ * <0: this < other
+ */
+ public int
+ cmp( OldFDBigIntForTest other ){
+ int i;
+ if ( this.nWords > other.nWords ){
+ // if any of my high-order words is non-zero,
+ // then the answer is evident
+ int j = other.nWords-1;
+ for ( i = this.nWords-1; i > j ; i-- )
+ if ( this.data[i] != 0 ) return 1;
+ }else if ( this.nWords < other.nWords ){
+ // if any of other's high-order words is non-zero,
+ // then the answer is evident
+ int j = this.nWords-1;
+ for ( i = other.nWords-1; i > j ; i-- )
+ if ( other.data[i] != 0 ) return -1;
+ } else{
+ i = this.nWords-1;
+ }
+ for ( ; i > 0 ; i-- )
+ if ( this.data[i] != other.data[i] )
+ break;
+ // careful! want unsigned compare!
+ // use brute force here.
+ int a = this.data[i];
+ int b = other.data[i];
+ if ( a < 0 ){
+ // a is really big, unsigned
+ if ( b < 0 ){
+ return a-b; // both big, negative
+ } else {
+ return 1; // b not big, answer is obvious;
+ }
+ } else {
+ // a is not really big
+ if ( b < 0 ) {
+ // but b is really big
+ return -1;
+ } else {
+ return a - b;
+ }
+ }
+ }
+
+ /*
+ * Compute
+ * q = (int)( this / S )
+ * this = 10 * ( this mod S )
+ * Return q.
+ * This is the iteration step of digit development for output.
+ * We assume that S has been normalized, as above, and that
+ * "this" has been lshift'ed accordingly.
+ * Also assume, of course, that the result, q, can be expressed
+ * as an integer, 0 <= q < 10.
+ */
+ public int
+ quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
+ // ensure that this and S have the same number of
+ // digits. If S is properly normalized and q < 10 then
+ // this must be so.
+ if ( nWords != S.nWords ){
+ throw new IllegalArgumentException("disparate values");
+ }
+ // estimate q the obvious way. We will usually be
+ // right. If not, then we're only off by a little and
+ // will re-add.
+ int n = nWords-1;
+ long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
+ long diff = 0L;
+ for ( int i = 0; i <= n ; i++ ){
+ diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
+ data[i] = (int)diff;
+ diff >>= 32; // N.B. SIGNED shift.
+ }
+ if ( diff != 0L ) {
+ // damn, damn, damn. q is too big.
+ // add S back in until this turns +. This should
+ // not be very many times!
+ long sum = 0L;
+ while ( sum == 0L ){
+ sum = 0L;
+ for ( int i = 0; i <= n; i++ ){
+ sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
+ data[i] = (int) sum;
+ sum >>= 32; // Signed or unsigned, answer is 0 or 1
+ }
+ /*
+ * Originally the following line read
+ * "if ( sum !=0 && sum != -1 )"
+ * but that would be wrong, because of the
+ * treatment of the two values as entirely unsigned,
+ * it would be impossible for a carry-out to be interpreted
+ * as -1 -- it would have to be a single-bit carry-out, or
+ * +1.
+ */
+ assert sum == 0 || sum == 1 : sum; // carry out of division correction
+ q -= 1;
+ }
+ }
+ // finally, we can multiply this by 10.
+ // it cannot overflow, right, as the high-order word has
+ // at least 4 high-order zeros!
+ long p = 0L;
+ for ( int i = 0; i <= n; i++ ){
+ p += 10*((long)data[i]&0xffffffffL);
+ data[i] = (int)p;
+ p >>= 32; // SIGNED shift.
+ }
+ assert p == 0L : p; // Carry out of *10
+ return (int)q;
+ }
+
+ public long
+ longValue(){
+ // if this can be represented as a long, return the value
+ assert this.nWords > 0 : this.nWords; // longValue confused
+
+ if (this.nWords == 1)
+ return ((long)data[0]&0xffffffffL);
+
+ assert dataInRangeIsZero(2, this.nWords, this); // value too big
+ assert data[1] >= 0; // value too big
+ return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
+ }
+
+ public String
+ toString() {
+ StringBuffer r = new StringBuffer(30);
+ r.append('[');
+ int i = Math.min( nWords-1, data.length-1) ;
+ if ( nWords > data.length ){
+ r.append( "("+data.length+"<"+nWords+"!)" );
+ }
+ for( ; i> 0 ; i-- ){
+ r.append( Integer.toHexString( data[i] ) );
+ r.append(' ');
+ }
+ r.append( Integer.toHexString( data[0] ) );
+ r.append(']');
+ return new String( r );
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/OldFloatingDecimalForTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,2434 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+//package jdk.internal.math;
+
+import java.util.regex.*;
+
+public class OldFloatingDecimalForTest{
+ boolean isExceptional;
+ boolean isNegative;
+ int decExponent;
+ char digits[];
+ int nDigits;
+ int bigIntExp;
+ int bigIntNBits;
+ boolean mustSetRoundDir = false;
+ boolean fromHex = false;
+ int roundDir = 0; // set by doubleValue
+
+ /*
+ * The fields below provides additional information about the result of
+ * the binary to decimal digits conversion done in dtoa() and roundup()
+ * methods. They are changed if needed by those two methods.
+ */
+
+ // True if the dtoa() binary to decimal conversion was exact.
+ boolean exactDecimalConversion = false;
+
+ // True if the result of the binary to decimal conversion was rounded-up
+ // at the end of the conversion process, i.e. roundUp() method was called.
+ boolean decimalDigitsRoundedUp = false;
+
+ private OldFloatingDecimalForTest( boolean negSign, int decExponent, char []digits, int n, boolean e )
+ {
+ isNegative = negSign;
+ isExceptional = e;
+ this.decExponent = decExponent;
+ this.digits = digits;
+ this.nDigits = n;
+ }
+
+ /*
+ * Constants of the implementation
+ * Most are IEEE-754 related.
+ * (There are more really boring constants at the end.)
+ */
+ static final long signMask = 0x8000000000000000L;
+ static final long expMask = 0x7ff0000000000000L;
+ static final long fractMask= ~(signMask|expMask);
+ static final int expShift = 52;
+ static final int expBias = 1023;
+ static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit
+ static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
+ static final int maxSmallBinExp = 62;
+ static final int minSmallBinExp = -( 63 / 3 );
+ static final int maxDecimalDigits = 15;
+ static final int maxDecimalExponent = 308;
+ static final int minDecimalExponent = -324;
+ static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
+
+ static final long highbyte = 0xff00000000000000L;
+ static final long highbit = 0x8000000000000000L;
+ static final long lowbytes = ~highbyte;
+
+ static final int singleSignMask = 0x80000000;
+ static final int singleExpMask = 0x7f800000;
+ static final int singleFractMask = ~(singleSignMask|singleExpMask);
+ static final int singleExpShift = 23;
+ static final int singleFractHOB = 1<<singleExpShift;
+ static final int singleExpBias = 127;
+ static final int singleMaxDecimalDigits = 7;
+ static final int singleMaxDecimalExponent = 38;
+ static final int singleMinDecimalExponent = -45;
+
+ static final int intDecimalDigits = 9;
+
+
+ /*
+ * count number of bits from high-order 1 bit to low-order 1 bit,
+ * inclusive.
+ */
+ private static int
+ countBits( long v ){
+ //
+ // the strategy is to shift until we get a non-zero sign bit
+ // then shift until we have no bits left, counting the difference.
+ // we do byte shifting as a hack. Hope it helps.
+ //
+ if ( v == 0L ) return 0;
+
+ while ( ( v & highbyte ) == 0L ){
+ v <<= 8;
+ }
+ while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
+ v <<= 1;
+ }
+
+ int n = 0;
+ while (( v & lowbytes ) != 0L ){
+ v <<= 8;
+ n += 8;
+ }
+ while ( v != 0L ){
+ v <<= 1;
+ n += 1;
+ }
+ return n;
+ }
+
+ /*
+ * Keep big powers of 5 handy for future reference.
+ */
+ private static OldFDBigIntForTest b5p[];
+
+ private static synchronized OldFDBigIntForTest
+ big5pow( int p ){
+ assert p >= 0 : p; // negative power of 5
+ if ( b5p == null ){
+ b5p = new OldFDBigIntForTest[ p+1 ];
+ }else if (b5p.length <= p ){
+ OldFDBigIntForTest t[] = new OldFDBigIntForTest[ p+1 ];
+ System.arraycopy( b5p, 0, t, 0, b5p.length );
+ b5p = t;
+ }
+ if ( b5p[p] != null )
+ return b5p[p];
+ else if ( p < small5pow.length )
+ return b5p[p] = new OldFDBigIntForTest( small5pow[p] );
+ else if ( p < long5pow.length )
+ return b5p[p] = new OldFDBigIntForTest( long5pow[p] );
+ else {
+ // construct the value.
+ // recursively.
+ int q, r;
+ // in order to compute 5^p,
+ // compute its square root, 5^(p/2) and square.
+ // or, let q = p / 2, r = p -q, then
+ // 5^p = 5^(q+r) = 5^q * 5^r
+ q = p >> 1;
+ r = p - q;
+ OldFDBigIntForTest bigq = b5p[q];
+ if ( bigq == null )
+ bigq = big5pow ( q );
+ if ( r < small5pow.length ){
+ return (b5p[p] = bigq.mult( small5pow[r] ) );
+ }else{
+ OldFDBigIntForTest bigr = b5p[ r ];
+ if ( bigr == null )
+ bigr = big5pow( r );
+ return (b5p[p] = bigq.mult( bigr ) );
+ }
+ }
+ }
+
+ //
+ // a common operation
+ //
+ private static OldFDBigIntForTest
+ multPow52( OldFDBigIntForTest v, int p5, int p2 ){
+ if ( p5 != 0 ){
+ if ( p5 < small5pow.length ){
+ v = v.mult( small5pow[p5] );
+ } else {
+ v = v.mult( big5pow( p5 ) );
+ }
+ }
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ //
+ // another common operation
+ //
+ private static OldFDBigIntForTest
+ constructPow52( int p5, int p2 ){
+ OldFDBigIntForTest v = new OldFDBigIntForTest( big5pow( p5 ) );
+ if ( p2 != 0 ){
+ v.lshiftMe( p2 );
+ }
+ return v;
+ }
+
+ /*
+ * Make a floating double into a OldFDBigIntForTest.
+ * This could also be structured as a OldFDBigIntForTest
+ * constructor, but we'd have to build a lot of knowledge
+ * about floating-point representation into it, and we don't want to.
+ *
+ * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ *
+ */
+ private OldFDBigIntForTest
+ doubleToBigInt( double dval ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ lbits &= fractMask;
+ if ( binexp > 0 ){
+ lbits |= fractHOB;
+ } else {
+ assert lbits != 0L : lbits; // doubleToBigInt(0.0)
+ binexp +=1;
+ while ( (lbits & fractHOB ) == 0L){
+ lbits <<= 1;
+ binexp -= 1;
+ }
+ }
+ binexp -= expBias;
+ int nbits = countBits( lbits );
+ /*
+ * We now know where the high-order 1 bit is,
+ * and we know how many there are.
+ */
+ int lowOrderZeros = expShift+1-nbits;
+ lbits >>>= lowOrderZeros;
+
+ bigIntExp = binexp+1-nbits;
+ bigIntNBits = nbits;
+ return new OldFDBigIntForTest( lbits );
+ }
+
+ /*
+ * Compute a number that is the ULP of the given value,
+ * for purposes of addition/subtraction. Generally easy.
+ * More difficult if subtracting and the argument
+ * is a normalized a power of 2, as the ULP changes at these points.
+ */
+ private static double ulp( double dval, boolean subtracting ){
+ long lbits = Double.doubleToLongBits( dval ) & ~signMask;
+ int binexp = (int)(lbits >>> expShift);
+ double ulpval;
+ if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
+ // for subtraction from normalized, powers of 2,
+ // use next-smaller exponent
+ binexp -= 1;
+ }
+ if ( binexp > expShift ){
+ ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
+ } else if ( binexp == 0 ){
+ ulpval = Double.MIN_VALUE;
+ } else {
+ ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
+ }
+ if ( subtracting ) ulpval = - ulpval;
+
+ return ulpval;
+ }
+
+ /*
+ * Round a double to a float.
+ * In addition to the fraction bits of the double,
+ * look at the class instance variable roundDir,
+ * which should help us avoid double-rounding error.
+ * roundDir was set in hardValueOf if the estimate was
+ * close enough, but not exact. It tells us which direction
+ * of rounding is preferred.
+ */
+ float
+ stickyRound( double dval ){
+ long lbits = Double.doubleToLongBits( dval );
+ long binexp = lbits & expMask;
+ if ( binexp == 0L || binexp == expMask ){
+ // what we have here is special.
+ // don't worry, the right thing will happen.
+ return (float) dval;
+ }
+ lbits += (long)roundDir; // hack-o-matic.
+ return (float)Double.longBitsToDouble( lbits );
+ }
+
+
+ /*
+ * This is the easy subcase --
+ * all the significant bits, after scaling, are held in lvalue.
+ * negSign and decExponent tell us what processing and scaling
+ * has already been done. Exceptional cases have already been
+ * stripped out.
+ * In particular:
+ * lvalue is a finite number (not Inf, nor NaN)
+ * lvalue > 0L (not zero, nor negative).
+ *
+ * The only reason that we develop the digits here, rather than
+ * calling on Long.toString() is that we can do it a little faster,
+ * and besides want to treat trailing 0s specially. If Long.toString
+ * changes, we should re-evaluate this strategy!
+ */
+ private void
+ developLongDigits( int decExponent, long lvalue, long insignificant ){
+ char digits[];
+ int ndigits;
+ int digitno;
+ int c;
+ //
+ // Discard non-significant low-order bits, while rounding,
+ // up to insignificant value.
+ int i;
+ for ( i = 0; insignificant >= 10L; i++ )
+ insignificant /= 10L;
+ if ( i != 0 ){
+ long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
+ long residue = lvalue % pow10;
+ lvalue /= pow10;
+ decExponent += i;
+ if ( residue >= (pow10>>1) ){
+ // round up based on the low-order bits we're discarding
+ lvalue++;
+ }
+ }
+ if ( lvalue <= Integer.MAX_VALUE ){
+ assert lvalue > 0L : lvalue; // lvalue <= 0
+ // even easier subcase!
+ // can do int arithmetic rather than long!
+ int ivalue = (int)lvalue;
+ ndigits = 10;
+ digits = perThreadBuffer.get();
+ digitno = ndigits-1;
+ c = ivalue%10;
+ ivalue /= 10;
+ while ( c == 0 ){
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ while ( ivalue != 0){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = ivalue%10;
+ ivalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ } else {
+ // same algorithm as above (same bugs, too )
+ // but using long arithmetic.
+ ndigits = 20;
+ digits = perThreadBuffer.get();
+ digitno = ndigits-1;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ while ( c == 0 ){
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10L;
+ }
+ while ( lvalue != 0L ){
+ digits[digitno--] = (char)(c+'0');
+ decExponent++;
+ c = (int)(lvalue%10L);
+ lvalue /= 10;
+ }
+ digits[digitno] = (char)(c+'0');
+ }
+ char result [];
+ ndigits -= digitno;
+ result = new char[ ndigits ];
+ System.arraycopy( digits, digitno, result, 0, ndigits );
+ this.digits = result;
+ this.decExponent = decExponent+1;
+ this.nDigits = ndigits;
+ }
+
+ //
+ // add one to the least significant digit.
+ // in the unlikely event there is a carry out,
+ // deal with it.
+ // assert that this will only happen where there
+ // is only one digit, e.g. (float)1e-44 seems to do it.
+ //
+ private void
+ roundup(){
+ int i;
+ int q = digits[ i = (nDigits-1)];
+ if ( q == '9' ){
+ while ( q == '9' && i > 0 ){
+ digits[i] = '0';
+ q = digits[--i];
+ }
+ if ( q == '9' ){
+ // carryout! High-order 1, rest 0s, larger exp.
+ decExponent += 1;
+ digits[0] = '1';
+ return;
+ }
+ // else fall through.
+ }
+ digits[i] = (char)(q+1);
+ decimalDigitsRoundedUp = true;
+ }
+
+ public boolean digitsRoundedUp() {
+ return decimalDigitsRoundedUp;
+ }
+
+ /*
+ * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
+ */
+ public OldFloatingDecimalForTest( double d )
+ {
+ long dBits = Double.doubleToLongBits( d );
+ long fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (dBits&signMask) != 0 ){
+ isNegative = true;
+ dBits ^= signMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (int)( (dBits&expMask) >> expShift );
+ fractBits = dBits&fractMask;
+ if ( binExp == (int)(expMask>>expShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0L ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&fractHOB) == 0L ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= fractHOB;
+ nSignificantBits = expShift+1;
+ }
+ binExp -= expBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, fractBits, nSignificantBits );
+ }
+
+ /*
+ * SECOND IMPORTANT CONSTRUCTOR: SINGLE
+ */
+ public OldFloatingDecimalForTest( float f )
+ {
+ int fBits = Float.floatToIntBits( f );
+ int fractBits;
+ int binExp;
+ int nSignificantBits;
+
+ // discover and delete sign
+ if ( (fBits&singleSignMask) != 0 ){
+ isNegative = true;
+ fBits ^= singleSignMask;
+ } else {
+ isNegative = false;
+ }
+ // Begin to unpack
+ // Discover obvious special cases of NaN and Infinity.
+ binExp = (fBits&singleExpMask) >> singleExpShift;
+ fractBits = fBits&singleFractMask;
+ if ( binExp == (singleExpMask>>singleExpShift) ) {
+ isExceptional = true;
+ if ( fractBits == 0L ){
+ digits = infinity;
+ } else {
+ digits = notANumber;
+ isNegative = false; // NaN has no sign!
+ }
+ nDigits = digits.length;
+ return;
+ }
+ isExceptional = false;
+ // Finish unpacking
+ // Normalize denormalized numbers.
+ // Insert assumed high-order bit for normalized numbers.
+ // Subtract exponent bias.
+ if ( binExp == 0 ){
+ if ( fractBits == 0 ){
+ // not a denorm, just a 0!
+ decExponent = 0;
+ digits = zero;
+ nDigits = 1;
+ return;
+ }
+ while ( (fractBits&singleFractHOB) == 0 ){
+ fractBits <<= 1;
+ binExp -= 1;
+ }
+ nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
+ binExp += 1;
+ } else {
+ fractBits |= singleFractHOB;
+ nSignificantBits = singleExpShift+1;
+ }
+ binExp -= singleExpBias;
+ // call the routine that actually does all the hard work.
+ dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
+ }
+
+ private void
+ dtoa( int binExp, long fractBits, int nSignificantBits )
+ {
+ int nFractBits; // number of significant bits of fractBits;
+ int nTinyBits; // number of these to the right of the point.
+ int decExp;
+
+ // Examine number. Determine if it is an easy case,
+ // which we can do pretty trivially using float/long conversion,
+ // or whether we must do real work.
+ nFractBits = countBits( fractBits );
+ nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
+ if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
+ // Look more closely at the number to decide if,
+ // with scaling by 10^nTinyBits, the result will fit in
+ // a long.
+ if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
+ /*
+ * We can do this:
+ * take the fraction bits, which are normalized.
+ * (a) nTinyBits == 0: Shift left or right appropriately
+ * to align the binary point at the extreme right, i.e.
+ * where a long int point is expected to be. The integer
+ * result is easily converted to a string.
+ * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
+ * which effectively converts to long and scales by
+ * 2^nTinyBits. Then multiply by 5^nTinyBits to
+ * complete the scaling. We know this won't overflow
+ * because we just counted the number of bits necessary
+ * in the result. The integer you get from this can
+ * then be converted to a string pretty easily.
+ */
+ long halfULP;
+ if ( nTinyBits == 0 ) {
+ if ( binExp > nSignificantBits ){
+ halfULP = 1L << ( binExp-nSignificantBits-1);
+ } else {
+ halfULP = 0L;
+ }
+ if ( binExp >= expShift ){
+ fractBits <<= (binExp-expShift);
+ } else {
+ fractBits >>>= (expShift-binExp) ;
+ }
+ developLongDigits( 0, fractBits, halfULP );
+ return;
+ }
+ /*
+ * The following causes excess digits to be printed
+ * out in the single-float case. Our manipulation of
+ * halfULP here is apparently not correct. If we
+ * better understand how this works, perhaps we can
+ * use this special case again. But for the time being,
+ * we do not.
+ * else {
+ * fractBits >>>= expShift+1-nFractBits;
+ * fractBits *= long5pow[ nTinyBits ];
+ * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
+ * developLongDigits( -nTinyBits, fractBits, halfULP );
+ * return;
+ * }
+ */
+ }
+ }
+ /*
+ * This is the hard case. We are going to compute large positive
+ * integers B and S and integer decExp, s.t.
+ * d = ( B / S ) * 10^decExp
+ * 1 <= B / S < 10
+ * Obvious choices are:
+ * decExp = floor( log10(d) )
+ * B = d * 2^nTinyBits * 10^max( 0, -decExp )
+ * S = 10^max( 0, decExp) * 2^nTinyBits
+ * (noting that nTinyBits has already been forced to non-negative)
+ * I am also going to compute a large positive integer
+ * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
+ * i.e. M is (1/2) of the ULP of d, scaled like B.
+ * When we iterate through dividing B/S and picking off the
+ * quotient bits, we will know when to stop when the remainder
+ * is <= M.
+ *
+ * We keep track of powers of 2 and powers of 5.
+ */
+
+ /*
+ * Estimate decimal exponent. (If it is small-ish,
+ * we could double-check.)
+ *
+ * First, scale the mantissa bits such that 1 <= d2 < 2.
+ * We are then going to estimate
+ * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
+ * and so we can estimate
+ * log10(d) ~=~ log10(d2) + binExp * log10(2)
+ * take the floor and call it decExp.
+ * FIXME -- use more precise constants here. It costs no more.
+ */
+ double d2 = Double.longBitsToDouble(
+ expOne | ( fractBits &~ fractHOB ) );
+ decExp = (int)Math.floor(
+ (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
+ int B2, B5; // powers of 2 and powers of 5, respectively, in B
+ int S2, S5; // powers of 2 and powers of 5, respectively, in S
+ int M2, M5; // powers of 2 and powers of 5, respectively, in M
+ int Bbits; // binary digits needed to represent B, approx.
+ int tenSbits; // binary digits needed to represent 10*S, approx.
+ OldFDBigIntForTest Sval, Bval, Mval;
+
+ B5 = Math.max( 0, -decExp );
+ B2 = B5 + nTinyBits + binExp;
+
+ S5 = Math.max( 0, decExp );
+ S2 = S5 + nTinyBits;
+
+ M5 = B5;
+ M2 = B2 - nSignificantBits;
+
+ /*
+ * the long integer fractBits contains the (nFractBits) interesting
+ * bits from the mantissa of d ( hidden 1 added if necessary) followed
+ * by (expShift+1-nFractBits) zeros. In the interest of compactness,
+ * I will shift out those zeros before turning fractBits into a
+ * OldFDBigIntForTest. The resulting whole number will be
+ * d * 2^(nFractBits-1-binExp).
+ */
+ fractBits >>>= (expShift+1-nFractBits);
+ B2 -= nFractBits-1;
+ int common2factor = Math.min( B2, S2 );
+ B2 -= common2factor;
+ S2 -= common2factor;
+ M2 -= common2factor;
+
+ /*
+ * HACK!! For exact powers of two, the next smallest number
+ * is only half as far away as we think (because the meaning of
+ * ULP changes at power-of-two bounds) for this reason, we
+ * hack M2. Hope this works.
+ */
+ if ( nFractBits == 1 )
+ M2 -= 1;
+
+ if ( M2 < 0 ){
+ // oops.
+ // since we cannot scale M down far enough,
+ // we must scale the other values up.
+ B2 -= M2;
+ S2 -= M2;
+ M2 = 0;
+ }
+ /*
+ * Construct, Scale, iterate.
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ char digits[] = this.digits = new char[18];
+ int ndigit = 0;
+ boolean low, high;
+ long lowDigitDifference;
+ int q;
+
+ /*
+ * Detect the special cases where all the numbers we are about
+ * to compute will fit in int or long integers.
+ * In these cases, we will avoid doing OldFDBigIntForTest arithmetic.
+ * We use the same algorithms, except that we "normalize"
+ * our OldFDBigIntForTests before iterating. This is to make division easier,
+ * as it makes our fist guess (quotient of high-order words)
+ * more accurate!
+ *
+ * Some day, we'll write a stopping test that takes
+ * account of the asymmetry of the spacing of floating-point
+ * numbers below perfect powers of 2
+ * 26 Sept 96 is not that day.
+ * So we use a symmetric test.
+ */
+ Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
+ tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
+ if ( Bbits < 64 && tenSbits < 64){
+ if ( Bbits < 32 && tenSbits < 32){
+ // wa-hoo! They're all ints!
+ int b = ((int)fractBits * small5pow[B5] ) << B2;
+ int s = small5pow[S5] << S2;
+ int m = small5pow[M5] << M2;
+ int tens = s * 10;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = b / s;
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ } else {
+ // still good! they're all longs!
+ long b = (fractBits * long5pow[B5] ) << B2;
+ long s = long5pow[S5] << S2;
+ long m = long5pow[M5] << M2;
+ long tens = s * 10L;
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = (int) ( b / s );
+ b = 10L * ( b % s );
+ m *= 10L;
+ low = (b < m );
+ high = (b+m > tens );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = (int) ( b / s );
+ b = 10 * ( b % s );
+ m *= 10;
+ assert q < 10 : q; // excessively large digit
+ if ( m > 0L ){
+ low = (b < m );
+ high = (b+m > tens );
+ } else {
+ // hack -- m might overflow!
+ // in this case, it is certainly > b,
+ // which won't
+ // and b+m > tens, too, since that has overflowed
+ // either!
+ low = true;
+ high = true;
+ }
+ digits[ndigit++] = (char)('0' + q);
+ }
+ lowDigitDifference = (b<<1) - tens;
+ exactDecimalConversion = (b == 0);
+ }
+ } else {
+ OldFDBigIntForTest ZeroVal = new OldFDBigIntForTest(0);
+ OldFDBigIntForTest tenSval;
+ int shiftBias;
+
+ /*
+ * We really must do OldFDBigIntForTest arithmetic.
+ * Fist, construct our OldFDBigIntForTest initial values.
+ */
+ Bval = multPow52( new OldFDBigIntForTest( fractBits ), B5, B2 );
+ Sval = constructPow52( S5, S2 );
+ Mval = constructPow52( M5, M2 );
+
+
+ // normalize so that division works better
+ Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
+ Mval.lshiftMe( shiftBias );
+ tenSval = Sval.mult( 10 );
+ /*
+ * Unroll the first iteration. If our decExp estimate
+ * was too high, our first quotient will be zero. In this
+ * case, we discard it and decrement decExp.
+ */
+ ndigit = 0;
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ assert q < 10 : q; // excessively large digit
+ if ( (q == 0) && ! high ){
+ // oops. Usually ignore leading zero.
+ decExp--;
+ } else {
+ digits[ndigit++] = (char)('0' + q);
+ }
+ /*
+ * HACK! Java spec sez that we always have at least
+ * one digit after the . in either F- or E-form output.
+ * Thus we will need more than one digit if we're using
+ * E-form
+ */
+ if ( decExp < -3 || decExp >= 8 ){
+ high = low = false;
+ }
+ while( ! low && ! high ){
+ q = Bval.quoRemIteration( Sval );
+ Mval = Mval.mult( 10 );
+ assert q < 10 : q; // excessively large digit
+ low = (Bval.cmp( Mval ) < 0);
+ high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
+ digits[ndigit++] = (char)('0' + q);
+ }
+ if ( high && low ){
+ Bval.lshiftMe(1);
+ lowDigitDifference = Bval.cmp(tenSval);
+ } else {
+ lowDigitDifference = 0L; // this here only for flow analysis!
+ }
+ exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0);
+ }
+ this.decExponent = decExp+1;
+ this.digits = digits;
+ this.nDigits = ndigit;
+ /*
+ * Last digit gets rounded based on stopping condition.
+ */
+ if ( high ){
+ if ( low ){
+ if ( lowDigitDifference == 0L ){
+ // it's a tie!
+ // choose based on which digits we like.
+ if ( (digits[nDigits-1]&1) != 0 ) roundup();
+ } else if ( lowDigitDifference > 0 ){
+ roundup();
+ }
+ } else {
+ roundup();
+ }
+ }
+ }
+
+ public boolean decimalDigitsExact() {
+ return exactDecimalConversion;
+ }
+
+ public String
+ toString(){
+ // most brain-dead version
+ StringBuffer result = new StringBuffer( nDigits+8 );
+ if ( isNegative ){ result.append( '-' ); }
+ if ( isExceptional ){
+ result.append( digits, 0, nDigits );
+ } else {
+ result.append( "0.");
+ result.append( digits, 0, nDigits );
+ result.append('e');
+ result.append( decExponent );
+ }
+ return new String(result);
+ }
+
+ public String toJavaFormatString() {
+ char result[] = perThreadBuffer.get();
+ int i = getChars(result);
+ return new String(result, 0, i);
+ }
+
+ private int getChars(char[] result) {
+ assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+ int i = 0;
+ if (isNegative) { result[0] = '-'; i = 1; }
+ if (isExceptional) {
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ if (decExponent > 0 && decExponent < 8) {
+ // print digits.digits.
+ int charLength = Math.min(nDigits, decExponent);
+ System.arraycopy(digits, 0, result, i, charLength);
+ i += charLength;
+ if (charLength < decExponent) {
+ charLength = decExponent-charLength;
+ System.arraycopy(zero, 0, result, i, charLength);
+ i += charLength;
+ result[i++] = '.';
+ result[i++] = '0';
+ } else {
+ result[i++] = '.';
+ if (charLength < nDigits) {
+ int t = nDigits - charLength;
+ System.arraycopy(digits, charLength, result, i, t);
+ i += t;
+ } else {
+ result[i++] = '0';
+ }
+ }
+ } else if (decExponent <=0 && decExponent > -3) {
+ result[i++] = '0';
+ result[i++] = '.';
+ if (decExponent != 0) {
+ System.arraycopy(zero, 0, result, i, -decExponent);
+ i -= decExponent;
+ }
+ System.arraycopy(digits, 0, result, i, nDigits);
+ i += nDigits;
+ } else {
+ result[i++] = digits[0];
+ result[i++] = '.';
+ if (nDigits > 1) {
+ System.arraycopy(digits, 1, result, i, nDigits-1);
+ i += nDigits-1;
+ } else {
+ result[i++] = '0';
+ }
+ result[i++] = 'E';
+ int e;
+ if (decExponent <= 0) {
+ result[i++] = '-';
+ e = -decExponent+1;
+ } else {
+ e = decExponent-1;
+ }
+ // decExponent has 1, 2, or 3, digits
+ if (e <= 9) {
+ result[i++] = (char)(e+'0');
+ } else if (e <= 99) {
+ result[i++] = (char)(e/10 +'0');
+ result[i++] = (char)(e%10 + '0');
+ } else {
+ result[i++] = (char)(e/100+'0');
+ e %= 100;
+ result[i++] = (char)(e/10+'0');
+ result[i++] = (char)(e%10 + '0');
+ }
+ }
+ }
+ return i;
+ }
+
+ // Per-thread buffer for string/stringbuffer conversion
+ private static ThreadLocal<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
+ protected synchronized char[] initialValue() {
+ return new char[26];
+ }
+ };
+
+ public void appendTo(Appendable buf) {
+ char result[] = perThreadBuffer.get();
+ int i = getChars(result);
+ if (buf instanceof StringBuilder)
+ ((StringBuilder) buf).append(result, 0, i);
+ else if (buf instanceof StringBuffer)
+ ((StringBuffer) buf).append(result, 0, i);
+ else
+ assert false;
+ }
+
+ @SuppressWarnings("fallthrough")
+ public static OldFloatingDecimalForTest
+ readJavaFormatString( String in ) throws NumberFormatException {
+ boolean isNegative = false;
+ boolean signSeen = false;
+ int decExp;
+ char c;
+
+ parseNumber:
+ try{
+ in = in.trim(); // don't fool around with white space.
+ // throws NullPointerException if null
+ int l = in.length();
+ if ( l == 0 ) throw new NumberFormatException("empty String");
+ int i = 0;
+ switch ( c = in.charAt( i ) ){
+ case '-':
+ isNegative = true;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ signSeen = true;
+ }
+
+ // Check for NaN and Infinity strings
+ c = in.charAt(i);
+ if(c == 'N' || c == 'I') { // possible NaN or infinity
+ boolean potentialNaN = false;
+ char targetChars[] = null; // char array of "NaN" or "Infinity"
+
+ if(c == 'N') {
+ targetChars = notANumber;
+ potentialNaN = true;
+ } else {
+ targetChars = infinity;
+ }
+
+ // compare Input string to "NaN" or "Infinity"
+ int j = 0;
+ while(i < l && j < targetChars.length) {
+ if(in.charAt(i) == targetChars[j]) {
+ i++; j++;
+ }
+ else // something is amiss, throw exception
+ break parseNumber;
+ }
+
+ // For the candidate string to be a NaN or infinity,
+ // all characters in input string and target char[]
+ // must be matched ==> j must equal targetChars.length
+ // and i must equal l
+ if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
+ return (potentialNaN ? new OldFloatingDecimalForTest(Double.NaN) // NaN has no sign
+ : new OldFloatingDecimalForTest(isNegative?
+ Double.NEGATIVE_INFINITY:
+ Double.POSITIVE_INFINITY)) ;
+ }
+ else { // something went wrong, throw exception
+ break parseNumber;
+ }
+
+ } else if (c == '0') { // check for hexadecimal floating-point number
+ if (l > i+1 ) {
+ char ch = in.charAt(i+1);
+ if (ch == 'x' || ch == 'X' ) // possible hex string
+ return parseHexString(in);
+ }
+ } // look for and process decimal floating-point string
+
+ char[] digits = new char[ l ];
+ int nDigits= 0;
+ boolean decSeen = false;
+ int decPt = 0;
+ int nLeadZero = 0;
+ int nTrailZero= 0;
+ digitLoop:
+ while ( i < l ){
+ switch ( c = in.charAt( i ) ){
+ case '0':
+ if ( nDigits > 0 ){
+ nTrailZero += 1;
+ } else {
+ nLeadZero += 1;
+ }
+ break; // out of switch.
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ while ( nTrailZero > 0 ){
+ digits[nDigits++] = '0';
+ nTrailZero -= 1;
+ }
+ digits[nDigits++] = c;
+ break; // out of switch.
+ case '.':
+ if ( decSeen ){
+ // already saw one ., this is the 2nd.
+ throw new NumberFormatException("multiple points");
+ }
+ decPt = i;
+ if ( signSeen ){
+ decPt -= 1;
+ }
+ decSeen = true;
+ break; // out of switch.
+ default:
+ break digitLoop;
+ }
+ i++;
+ }
+ /*
+ * At this point, we've scanned all the digits and decimal
+ * point we're going to see. Trim off leading and trailing
+ * zeros, which will just confuse us later, and adjust
+ * our initial decimal exponent accordingly.
+ * To review:
+ * we have seen i total characters.
+ * nLeadZero of them were zeros before any other digits.
+ * nTrailZero of them were zeros after any other digits.
+ * if ( decSeen ), then a . was seen after decPt characters
+ * ( including leading zeros which have been discarded )
+ * nDigits characters were neither lead nor trailing
+ * zeros, nor point
+ */
+ /*
+ * special hack: if we saw no non-zero digits, then the
+ * answer is zero!
+ * Unfortunately, we feel honor-bound to keep parsing!
+ */
+ if ( nDigits == 0 ){
+ digits = zero;
+ nDigits = 1;
+ if ( nLeadZero == 0 ){
+ // we saw NO DIGITS AT ALL,
+ // not even a crummy 0!
+ // this is not allowed.
+ break parseNumber; // go throw exception
+ }
+
+ }
+
+ /* Our initial exponent is decPt, adjusted by the number of
+ * discarded zeros. Or, if there was no decPt,
+ * then its just nDigits adjusted by discarded trailing zeros.
+ */
+ if ( decSeen ){
+ decExp = decPt - nLeadZero;
+ } else {
+ decExp = nDigits+nTrailZero;
+ }
+
+ /*
+ * Look for 'e' or 'E' and an optionally signed integer.
+ */
+ if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+ int expSign = 1;
+ int expVal = 0;
+ int reallyBig = Integer.MAX_VALUE / 10;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
+ }
+ int expAt = i;
+ expLoop:
+ while ( i < l ){
+ if ( expVal >= reallyBig ){
+ // the next character will cause integer
+ // overflow.
+ expOverflow = true;
+ }
+ switch ( c = in.charAt(i++) ){
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ expVal = expVal*10 + ( (int)c - (int)'0' );
+ continue;
+ default:
+ i--; // back up.
+ break expLoop; // stop parsing exponent.
+ }
+ }
+ int expLimit = bigDecimalExponent+nDigits+nTrailZero;
+ if ( expOverflow || ( expVal > expLimit ) ){
+ //
+ // The intent here is to end up with
+ // infinity or zero, as appropriate.
+ // The reason for yielding such a small decExponent,
+ // rather than something intuitive such as
+ // expSign*Integer.MAX_VALUE, is that this value
+ // is subject to further manipulation in
+ // doubleValue() and floatValue(), and I don't want
+ // it to be able to cause overflow there!
+ // (The only way we can get into trouble here is for
+ // really outrageous nDigits+nTrailZero, such as 2 billion. )
+ //
+ decExp = expSign*expLimit;
+ } else {
+ // this should not overflow, since we tested
+ // for expVal > (MAX+N), where N >= abs(decExp)
+ decExp = decExp + expSign*expVal;
+ }
+
+ // if we saw something not a digit ( or end of string )
+ // after the [Ee][+-], without seeing any digits at all
+ // this is certainly an error. If we saw some digits,
+ // but then some trailing garbage, that might be ok.
+ // so we just fall through in that case.
+ // HUMBUG
+ if ( i == expAt )
+ break parseNumber; // certainly bad
+ }
+ /*
+ * We parsed everything we could.
+ * If there are leftovers, then this is not good input!
+ */
+ if ( i < l &&
+ ((i != l - 1) ||
+ (in.charAt(i) != 'f' &&
+ in.charAt(i) != 'F' &&
+ in.charAt(i) != 'd' &&
+ in.charAt(i) != 'D'))) {
+ break parseNumber; // go throw exception
+ }
+
+ return new OldFloatingDecimalForTest( isNegative, decExp, digits, nDigits, false );
+ } catch ( StringIndexOutOfBoundsException e ){ }
+ throw new NumberFormatException("For input string: \"" + in + "\"");
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value is, as a double.
+ *
+ * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+ * ROUNDING DIRECTION in case the result is really destined
+ * for a single-precision float.
+ */
+
+ public strictfp double doubleValue(){
+ int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
+ long lValue;
+ double dValue;
+ double rValue, tValue;
+
+ // First, check for NaN and Infinity values
+ if(digits == infinity || digits == notANumber) {
+ if(digits == notANumber)
+ return Double.NaN;
+ else
+ return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
+ }
+ else {
+ if (mustSetRoundDir) {
+ roundDir = 0;
+ }
+ /*
+ * convert the lead kDigits to a long integer.
+ */
+ // (special performance hack: start to do it using int)
+ int iValue = (int)digits[0]-(int)'0';
+ int iDigits = Math.min( kDigits, intDecimalDigits );
+ for ( int i=1; i < iDigits; i++ ){
+ iValue = iValue*10 + (int)digits[i]-(int)'0';
+ }
+ lValue = (long)iValue;
+ for ( int i=iDigits; i < kDigits; i++ ){
+ lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ dValue = (double)lValue;
+ int exp = decExponent-kDigits;
+ /*
+ * lValue now contains a long integer with the value of
+ * the first kDigits digits of the number.
+ * dValue contains the (double) of the same.
+ */
+
+ if ( nDigits <= maxDecimalDigits ){
+ /*
+ * possibly an easy case.
+ * We know that the digits can be represented
+ * exactly. And if the exponent isn't too outrageous,
+ * the whole thing can be done with one operation,
+ * thus one rounding error.
+ * Note that all our constructors trim all leading and
+ * trailing zeros, so simple values (including zero)
+ * will always end up here
+ */
+ if (exp == 0 || dValue == 0.0)
+ return (isNegative)? -dValue : dValue; // small floating integer
+ else if ( exp >= 0 ){
+ if ( exp <= maxSmallTen ){
+ /*
+ * Can get the answer with one operation,
+ * thus one roundoff.
+ */
+ rValue = dValue * small10pow[exp];
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ int slop = maxDecimalDigits - kDigits;
+ if ( exp <= maxSmallTen+slop ){
+ /*
+ * We can multiply dValue by 10^(slop)
+ * and it is still "small" and exact.
+ * Then we can multiply by 10^(exp-slop)
+ * with one rounding.
+ */
+ dValue *= small10pow[slop];
+ rValue = dValue * small10pow[exp-slop];
+
+ if ( mustSetRoundDir ){
+ tValue = rValue / small10pow[exp-slop];
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a positive exp.
+ */
+ } else {
+ if ( exp >= -maxSmallTen ){
+ /*
+ * Can get the answer in one division.
+ */
+ rValue = dValue / small10pow[-exp];
+ tValue = rValue * small10pow[-exp];
+ if ( mustSetRoundDir ){
+ roundDir = ( tValue == dValue ) ? 0
+ :( tValue < dValue ) ? 1
+ : -1;
+ }
+ return (isNegative)? -rValue : rValue;
+ }
+ /*
+ * Else we have a hard case with a negative exp.
+ */
+ }
+ }
+
+ /*
+ * Harder cases:
+ * The sum of digits plus exponent is greater than
+ * what we think we can do with one error.
+ *
+ * Start by approximating the right answer by,
+ * naively, scaling by powers of 10.
+ */
+ if ( exp > 0 ){
+ if ( decExponent > maxDecimalExponent+1 ){
+ /*
+ * Lets face it. This is going to be
+ * Infinity. Cut to the chase.
+ */
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ if ( (exp&15) != 0 ){
+ dValue *= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= big10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could overflow.
+ */
+ double t = dValue * big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ /*
+ * It did overflow.
+ * Look more closely at the result.
+ * If the exponent is just one too large,
+ * then use the maximum finite as our estimate
+ * value. Else call the result infinity
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two larger than
+ * Double.MAX_VALUE ).
+ */
+ t = dValue / 2.0;
+ t *= big10pow[j];
+ if ( Double.isInfinite( t ) ){
+ return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+ }
+ t = Double.MAX_VALUE;
+ }
+ dValue = t;
+ }
+ } else if ( exp < 0 ){
+ exp = -exp;
+ if ( decExponent < minDecimalExponent-1 ){
+ /*
+ * Lets face it. This is going to be
+ * zero. Cut to the chase.
+ */
+ return (isNegative)? -0.0 : 0.0;
+ }
+ if ( (exp&15) != 0 ){
+ dValue /= small10pow[exp&15];
+ }
+ if ( (exp>>=4) != 0 ){
+ int j;
+ for( j = 0; exp > 1; j++, exp>>=1 ){
+ if ( (exp&1)!=0)
+ dValue *= tiny10pow[j];
+ }
+ /*
+ * The reason for the weird exp > 1 condition
+ * in the above loop was so that the last multiply
+ * would get unrolled. We handle it here.
+ * It could underflow.
+ */
+ double t = dValue * tiny10pow[j];
+ if ( t == 0.0 ){
+ /*
+ * It did underflow.
+ * Look more closely at the result.
+ * If the exponent is just one too small,
+ * then use the minimum finite as our estimate
+ * value. Else call the result 0.0
+ * and punt it.
+ * ( I presume this could happen because
+ * rounding forces the result here to be
+ * an ULP or two less than
+ * Double.MIN_VALUE ).
+ */
+ t = dValue * 2.0;
+ t *= tiny10pow[j];
+ if ( t == 0.0 ){
+ return (isNegative)? -0.0 : 0.0;
+ }
+ t = Double.MIN_VALUE;
+ }
+ dValue = t;
+ }
+ }
+
+ /*
+ * dValue is now approximately the result.
+ * The hard part is adjusting it, by comparison
+ * with OldFDBigIntForTest arithmetic.
+ * Formulate the EXACT big-number result as
+ * bigD0 * 10^exp
+ */
+ OldFDBigIntForTest bigD0 = new OldFDBigIntForTest( lValue, digits, kDigits, nDigits );
+ exp = decExponent - nDigits;
+
+ correctionLoop:
+ while(true){
+ /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
+ * bigIntExp and bigIntNBits
+ */
+ OldFDBigIntForTest bigB = doubleToBigInt( dValue );
+
+ /*
+ * Scale bigD, bigB appropriately for
+ * big-integer operations.
+ * Naively, we multiply by powers of ten
+ * and powers of two. What we actually do
+ * is keep track of the powers of 5 and
+ * powers of 2 we would use, then factor out
+ * common divisors before doing the work.
+ */
+ int B2, B5; // powers of 2, 5 in bigB
+ int D2, D5; // powers of 2, 5 in bigD
+ int Ulp2; // powers of 2 in halfUlp.
+ if ( exp >= 0 ){
+ B2 = B5 = 0;
+ D2 = D5 = exp;
+ } else {
+ B2 = B5 = -exp;
+ D2 = D5 = 0;
+ }
+ if ( bigIntExp >= 0 ){
+ B2 += bigIntExp;
+ } else {
+ D2 -= bigIntExp;
+ }
+ Ulp2 = B2;
+ // shift bigB and bigD left by a number s. t.
+ // halfUlp is still an integer.
+ int hulpbias;
+ if ( bigIntExp+bigIntNBits <= -expBias+1 ){
+ // This is going to be a denormalized number
+ // (if not actually zero).
+ // half an ULP is at 2^-(expBias+expShift+1)
+ hulpbias = bigIntExp+ expBias + expShift;
+ } else {
+ hulpbias = expShift + 2 - bigIntNBits;
+ }
+ B2 += hulpbias;
+ D2 += hulpbias;
+ // if there are common factors of 2, we might just as well
+ // factor them out, as they add nothing useful.
+ int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
+ B2 -= common2;
+ D2 -= common2;
+ Ulp2 -= common2;
+ // do multiplications by powers of 5 and 2
+ bigB = multPow52( bigB, B5, B2 );
+ OldFDBigIntForTest bigD = multPow52( new OldFDBigIntForTest( bigD0 ), D5, D2 );
+ //
+ // to recap:
+ // bigB is the scaled-big-int version of our floating-point
+ // candidate.
+ // bigD is the scaled-big-int version of the exact value
+ // as we understand it.
+ // halfUlp is 1/2 an ulp of bigB, except for special cases
+ // of exact powers of 2
+ //
+ // the plan is to compare bigB with bigD, and if the difference
+ // is less than halfUlp, then we're satisfied. Otherwise,
+ // use the ratio of difference to halfUlp to calculate a fudge
+ // factor to add to the floating value, then go 'round again.
+ //
+ OldFDBigIntForTest diff;
+ int cmpResult;
+ boolean overvalue;
+ if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
+ overvalue = true; // our candidate is too big.
+ diff = bigB.sub( bigD );
+ if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
+ // candidate is a normalized exact power of 2 and
+ // is too big. We will be subtracting.
+ // For our purposes, ulp is the ulp of the
+ // next smaller range.
+ Ulp2 -= 1;
+ if ( Ulp2 < 0 ){
+ // rats. Cannot de-scale ulp this far.
+ // must scale diff in other direction.
+ Ulp2 = 0;
+ diff.lshiftMe( 1 );
+ }
+ }
+ } else if ( cmpResult < 0 ){
+ overvalue = false; // our candidate is too small.
+ diff = bigD.sub( bigB );
+ } else {
+ // the candidate is exactly right!
+ // this happens with surprising frequency
+ break correctionLoop;
+ }
+ OldFDBigIntForTest halfUlp = constructPow52( B5, Ulp2 );
+ if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
+ // difference is small.
+ // this is close enough
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else if ( cmpResult == 0 ){
+ // difference is exactly half an ULP
+ // round to some other value maybe, then finish
+ dValue += 0.5*ulp( dValue, overvalue );
+ // should check for bigIntNBits == 1 here??
+ if (mustSetRoundDir) {
+ roundDir = overvalue ? -1 : 1;
+ }
+ break correctionLoop;
+ } else {
+ // difference is non-trivial.
+ // could scale addend by ratio of difference to
+ // halfUlp here, if we bothered to compute that difference.
+ // Most of the time ( I hope ) it is about 1 anyway.
+ dValue += ulp( dValue, overvalue );
+ if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
+ break correctionLoop; // oops. Fell off end of range.
+ continue; // try again.
+ }
+
+ }
+ return (isNegative)? -dValue : dValue;
+ }
+ }
+
+ /*
+ * Take a FloatingDecimal, which we presumably just scanned in,
+ * and find out what its value is, as a float.
+ * This is distinct from doubleValue() to avoid the extremely
+ * unlikely case of a double rounding error, wherein the conversion
+ * to double has one rounding error, and the conversion of that double
+ * to a float has another rounding error, IN THE WRONG DIRECTION,
+ * ( because of the preference to a zero low-order bit ).
+ */
+
+ public strictfp float floatValue(){
+ int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
+ int iValue;
+ float fValue;
+
+ // First, check for NaN and Infinity values
+ if(digits == infinity || digits == notANumber) {
+ if(digits == notANumber)
+ return Float.NaN;
+ else
+ return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
+ }
+ else {
+ /*
+ * convert the lead kDigits to an integer.
+ */
+ iValue = (int)digits[0]-(int)'0';
+ for ( int i=1; i < kDigits; i++ ){
+ iValue = iValue*10 + (int)digits[i]-(int)'0';
+ }
+ fValue = (float)iValue;
+ int exp = decExponent-kDigits;
+ /*
+ * iValue now contains an integer with the value of
+ * the first kDigits digits of the number.
+ * fValue contains the (float) of the same.
+ */
+
+ if ( nDigits <= singleMaxDecimalDigits ){
+ /*
+ * possibly an easy case.
+ * We know that the digits can be represented
+ * exactly. And if the exponent isn't too outrageous,
+ * the whole thing can be done with one operation,
+ * thus one rounding error.
+ * Note that all our constructors trim all leading and
+ * trailing zeros, so simple values (including zero)
+ * will always end up here.
+ */
+ if (exp == 0 || fValue == 0.0f)
+ return (isNegative)? -fValue : fValue; // small floating integer
+ else if ( exp >= 0 ){
+ if ( exp <= singleMaxSmallTen ){
+ /*
+ * Can get the answer with one operation,
+ * thus one roundoff.
+ */
+ fValue *= singleSmall10pow[exp];
+ return (isNegative)? -fValue : fValue;
+ }
+ int slop = singleMaxDecimalDigits - kDigits;
+ if ( exp <= singleMaxSmallTen+slop ){
+ /*
+ * We can multiply dValue by 10^(slop)
+ * and it is still "small" and exact.
+ * Then we can multiply by 10^(exp-slop)
+ * with one rounding.
+ */
+ fValue *= singleSmall10pow[slop];
+ fValue *= singleSmall10pow[exp-slop];
+ return (isNegative)? -fValue : fValue;
+ }
+ /*
+ * Else we have a hard case with a positive exp.
+ */
+ } else {
+ if ( exp >= -singleMaxSmallTen ){
+ /*
+ * Can get the answer in one division.
+ */
+ fValue /= singleSmall10pow[-exp];
+ return (isNegative)? -fValue : fValue;
+ }
+ /*
+ * Else we have a hard case with a negative exp.
+ */
+ }
+ } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
+ /*
+ * In double-precision, this is an exact floating integer.
+ * So we can compute to double, then shorten to float
+ * with one round, and get the right answer.
+ *
+ * First, finish accumulating digits.
+ * Then convert that integer to a double, multiply
+ * by the appropriate power of ten, and convert to float.
+ */
+ long lValue = (long)iValue;
+ for ( int i=kDigits; i < nDigits; i++ ){
+ lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
+ }
+ double dValue = (double)lValue;
+ exp = decExponent-nDigits;
+ dValue *= small10pow[exp];
+ fValue = (float)dValue;
+ return (isNegative)? -fValue : fValue;
+
+ }
+ /*
+ * Harder cases:
+ * The sum of digits plus exponent is greater than
+ * what we think we can do with one error.
+ *
+ * Start by weeding out obviously out-of-range
+ * results, then convert to double and go to
+ * common hard-case code.
+ */
+ if ( decExponent > singleMaxDecimalExponent+1 ){
+ /*
+ * Lets face it. This is going to be
+ * Infinity. Cut to the chase.
+ */
+ return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+ } else if ( decExponent < singleMinDecimalExponent-1 ){
+ /*
+ * Lets face it. This is going to be
+ * zero. Cut to the chase.
+ */
+ return (isNegative)? -0.0f : 0.0f;
+ }
+
+ /*
+ * Here, we do 'way too much work, but throwing away
+ * our partial results, and going and doing the whole
+ * thing as double, then throwing away half the bits that computes
+ * when we convert back to float.
+ *
+ * The alternative is to reproduce the whole multiple-precision
+ * algorithm for float precision, or to try to parameterize it
+ * for common usage. The former will take about 400 lines of code,
+ * and the latter I tried without success. Thus the semi-hack
+ * answer here.
+ */
+ mustSetRoundDir = !fromHex;
+ double dValue = doubleValue();
+ return stickyRound( dValue );
+ }
+ }
+
+
+ /*
+ * All the positive powers of 10 that can be
+ * represented exactly in double/float.
+ */
+ private static final double small10pow[] = {
+ 1.0e0,
+ 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+ 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+ 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+ 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+ 1.0e21, 1.0e22
+ };
+
+ private static final float singleSmall10pow[] = {
+ 1.0e0f,
+ 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+ 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+ };
+
+ private static final double big10pow[] = {
+ 1e16, 1e32, 1e64, 1e128, 1e256 };
+ private static final double tiny10pow[] = {
+ 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+ private static final int maxSmallTen = small10pow.length-1;
+ private static final int singleMaxSmallTen = singleSmall10pow.length-1;
+
+ private static final int small5pow[] = {
+ 1,
+ 5,
+ 5*5,
+ 5*5*5,
+ 5*5*5*5,
+ 5*5*5*5*5,
+ 5*5*5*5*5*5,
+ 5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5*5,
+ 5*5*5*5*5*5*5*5*5*5*5*5*5
+ };
+
+
+ private static final long long5pow[] = {
+ 1L,
+ 5L,
+ 5L*5,
+ 5L*5*5,
+ 5L*5*5*5,
+ 5L*5*5*5*5,
+ 5L*5*5*5*5*5,
+ 5L*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
+ };
+
+ // approximately ceil( log2( long5pow[i] ) )
+ private static final int n5bits[] = {
+ 0,
+ 3,
+ 5,
+ 7,
+ 10,
+ 12,
+ 14,
+ 17,
+ 19,
+ 21,
+ 24,
+ 26,
+ 28,
+ 31,
+ 33,
+ 35,
+ 38,
+ 40,
+ 42,
+ 45,
+ 47,
+ 49,
+ 52,
+ 54,
+ 56,
+ 59,
+ 61,
+ };
+
+ private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
+ private static final char notANumber[] = { 'N', 'a', 'N' };
+ private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
+
+
+ /*
+ * Grammar is compatible with hexadecimal floating-point constants
+ * described in section 6.4.4.2 of the C99 specification.
+ */
+ private static Pattern hexFloatPattern = null;
+ private static synchronized Pattern getHexFloatPattern() {
+ if (hexFloatPattern == null) {
+ hexFloatPattern = Pattern.compile(
+ //1 234 56 7 8 9
+ "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+ );
+ }
+ return hexFloatPattern;
+ }
+
+ /*
+ * Convert string s to a suitable floating decimal; uses the
+ * double constructor and set the roundDir variable appropriately
+ * in case the value is later converted to a float.
+ */
+ static OldFloatingDecimalForTest parseHexString(String s) {
+ // Verify string is a member of the hexadecimal floating-point
+ // string language.
+ Matcher m = getHexFloatPattern().matcher(s);
+ boolean validInput = m.matches();
+
+ if (!validInput) {
+ // Input does not match pattern
+ throw new NumberFormatException("For input string: \"" + s + "\"");
+ } else { // validInput
+ /*
+ * We must isolate the sign, significand, and exponent
+ * fields. The sign value is straightforward. Since
+ * floating-point numbers are stored with a normalized
+ * representation, the significand and exponent are
+ * interrelated.
+ *
+ * After extracting the sign, we normalized the
+ * significand as a hexadecimal value, calculating an
+ * exponent adjust for any shifts made during
+ * normalization. If the significand is zero, the
+ * exponent doesn't need to be examined since the output
+ * will be zero.
+ *
+ * Next the exponent in the input string is extracted.
+ * Afterwards, the significand is normalized as a *binary*
+ * value and the input value's normalized exponent can be
+ * computed. The significand bits are copied into a
+ * double significand; if the string has more logical bits
+ * than can fit in a double, the extra bits affect the
+ * round and sticky bits which are used to round the final
+ * value.
+ */
+
+ // Extract significand sign
+ String group1 = m.group(1);
+ double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
+
+
+ // Extract Significand magnitude
+ /*
+ * Based on the form of the significand, calculate how the
+ * binary exponent needs to be adjusted to create a
+ * normalized *hexadecimal* floating-point number; that
+ * is, a number where there is one nonzero hex digit to
+ * the left of the (hexa)decimal point. Since we are
+ * adjusting a binary, not hexadecimal exponent, the
+ * exponent is adjusted by a multiple of 4.
+ *
+ * There are a number of significand scenarios to consider;
+ * letters are used in indicate nonzero digits:
+ *
+ * 1. 000xxxx => x.xxx normalized
+ * increase exponent by (number of x's - 1)*4
+ *
+ * 2. 000xxx.yyyy => x.xxyyyy normalized
+ * increase exponent by (number of x's - 1)*4
+ *
+ * 3. .000yyy => y.yy normalized
+ * decrease exponent by (number of zeros + 1)*4
+ *
+ * 4. 000.00000yyy => y.yy normalized
+ * decrease exponent by (number of zeros to right of point + 1)*4
+ *
+ * If the significand is exactly zero, return a properly
+ * signed zero.
+ */
+
+ String significandString =null;
+ int signifLength = 0;
+ int exponentAdjust = 0;
+ {
+ int leftDigits = 0; // number of meaningful digits to
+ // left of "decimal" point
+ // (leading zeros stripped)
+ int rightDigits = 0; // number of digits to right of
+ // "decimal" point; leading zeros
+ // must always be accounted for
+ /*
+ * The significand is made up of either
+ *
+ * 1. group 4 entirely (integer portion only)
+ *
+ * OR
+ *
+ * 2. the fractional portion from group 7 plus any
+ * (optional) integer portions from group 6.
+ */
+ String group4;
+ if( (group4 = m.group(4)) != null) { // Integer-only significand
+ // Leading zeros never matter on the integer portion
+ significandString = stripLeadingZeros(group4);
+ leftDigits = significandString.length();
+ }
+ else {
+ // Group 6 is the optional integer; leading zeros
+ // never matter on the integer portion
+ String group6 = stripLeadingZeros(m.group(6));
+ leftDigits = group6.length();
+
+ // fraction
+ String group7 = m.group(7);
+ rightDigits = group7.length();
+
+ // Turn "integer.fraction" into "integer"+"fraction"
+ significandString =
+ ((group6 == null)?"":group6) + // is the null
+ // check necessary?
+ group7;
+ }
+
+ significandString = stripLeadingZeros(significandString);
+ signifLength = significandString.length();
+
+ /*
+ * Adjust exponent as described above
+ */
+ if (leftDigits >= 1) { // Cases 1 and 2
+ exponentAdjust = 4*(leftDigits - 1);
+ } else { // Cases 3 and 4
+ exponentAdjust = -4*( rightDigits - signifLength + 1);
+ }
+
+ // If the significand is zero, the exponent doesn't
+ // matter; return a properly signed zero.
+
+ if (signifLength == 0) { // Only zeros in input
+ return new OldFloatingDecimalForTest(sign * 0.0);
+ }
+ }
+
+ // Extract Exponent
+ /*
+ * Use an int to read in the exponent value; this should
+ * provide more than sufficient range for non-contrived
+ * inputs. If reading the exponent in as an int does
+ * overflow, examine the sign of the exponent and
+ * significand to determine what to do.
+ */
+ String group8 = m.group(8);
+ boolean positiveExponent = ( group8 == null ) || group8.equals("+");
+ long unsignedRawExponent;
+ try {
+ unsignedRawExponent = Integer.parseInt(m.group(9));
+ }
+ catch (NumberFormatException e) {
+ // At this point, we know the exponent is
+ // syntactically well-formed as a sequence of
+ // digits. Therefore, if an NumberFormatException
+ // is thrown, it must be due to overflowing int's
+ // range. Also, at this point, we have already
+ // checked for a zero significand. Thus the signs
+ // of the exponent and significand determine the
+ // final result:
+ //
+ // significand
+ // + -
+ // exponent + +infinity -infinity
+ // - +0.0 -0.0
+ return new OldFloatingDecimalForTest(sign * (positiveExponent ?
+ Double.POSITIVE_INFINITY : 0.0));
+ }
+
+ long rawExponent =
+ (positiveExponent ? 1L : -1L) * // exponent sign
+ unsignedRawExponent; // exponent magnitude
+
+ // Calculate partially adjusted exponent
+ long exponent = rawExponent + exponentAdjust ;
+
+ // Starting copying non-zero bits into proper position in
+ // a long; copy explicit bit too; this will be masked
+ // later for normal values.
+
+ boolean round = false;
+ boolean sticky = false;
+ int bitsCopied=0;
+ int nextShift=0;
+ long significand=0L;
+ // First iteration is different, since we only copy
+ // from the leading significand bit; one more exponent
+ // adjust will be needed...
+
+ // IMPORTANT: make leadingDigit a long to avoid
+ // surprising shift semantics!
+ long leadingDigit = getHexDigit(significandString, 0);
+
+ /*
+ * Left shift the leading digit (53 - (bit position of
+ * leading 1 in digit)); this sets the top bit of the
+ * significand to 1. The nextShift value is adjusted
+ * to take into account the number of bit positions of
+ * the leadingDigit actually used. Finally, the
+ * exponent is adjusted to normalize the significand
+ * as a binary value, not just a hex value.
+ */
+ if (leadingDigit == 1) {
+ significand |= leadingDigit << 52;
+ nextShift = 52 - 4;
+ /* exponent += 0 */ }
+ else if (leadingDigit <= 3) { // [2, 3]
+ significand |= leadingDigit << 51;
+ nextShift = 52 - 5;
+ exponent += 1;
+ }
+ else if (leadingDigit <= 7) { // [4, 7]
+ significand |= leadingDigit << 50;
+ nextShift = 52 - 6;
+ exponent += 2;
+ }
+ else if (leadingDigit <= 15) { // [8, f]
+ significand |= leadingDigit << 49;
+ nextShift = 52 - 7;
+ exponent += 3;
+ } else {
+ throw new AssertionError("Result from digit conversion too large!");
+ }
+ // The preceding if-else could be replaced by a single
+ // code block based on the high-order bit set in
+ // leadingDigit. Given leadingOnePosition,
+
+ // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+ // nextShift = 52 - (3 + leadingOnePosition);
+ // exponent += (leadingOnePosition-1);
+
+
+ /*
+ * Now the exponent variable is equal to the normalized
+ * binary exponent. Code below will make representation
+ * adjustments if the exponent is incremented after
+ * rounding (includes overflows to infinity) or if the
+ * result is subnormal.
+ */
+
+ // Copy digit into significand until the significand can't
+ // hold another full hex digit or there are no more input
+ // hex digits.
+ int i = 0;
+ for(i = 1;
+ i < signifLength && nextShift >= 0;
+ i++) {
+ long currentDigit = getHexDigit(significandString, i);
+ significand |= (currentDigit << nextShift);
+ nextShift-=4;
+ }
+
+ // After the above loop, the bulk of the string is copied.
+ // Now, we must copy any partial hex digits into the
+ // significand AND compute the round bit and start computing
+ // sticky bit.
+
+ if ( i < signifLength ) { // at least one hex input digit exists
+ long currentDigit = getHexDigit(significandString, i);
+
+ // from nextShift, figure out how many bits need
+ // to be copied, if any
+ switch(nextShift) { // must be negative
+ case -1:
+ // three bits need to be copied in; can
+ // set round bit
+ significand |= ((currentDigit & 0xEL) >> 1);
+ round = (currentDigit & 0x1L) != 0L;
+ break;
+
+ case -2:
+ // two bits need to be copied in; can
+ // set round and start sticky
+ significand |= ((currentDigit & 0xCL) >> 2);
+ round = (currentDigit &0x2L) != 0L;
+ sticky = (currentDigit & 0x1L) != 0;
+ break;
+
+ case -3:
+ // one bit needs to be copied in
+ significand |= ((currentDigit & 0x8L)>>3);
+ // Now set round and start sticky, if possible
+ round = (currentDigit &0x4L) != 0L;
+ sticky = (currentDigit & 0x3L) != 0;
+ break;
+
+ case -4:
+ // all bits copied into significand; set
+ // round and start sticky
+ round = ((currentDigit & 0x8L) != 0); // is top bit set?
+ // nonzeros in three low order bits?
+ sticky = (currentDigit & 0x7L) != 0;
+ break;
+
+ default:
+ throw new AssertionError("Unexpected shift distance remainder.");
+ // break;
+ }
+
+ // Round is set; sticky might be set.
+
+ // For the sticky bit, it suffices to check the
+ // current digit and test for any nonzero digits in
+ // the remaining unprocessed input.
+ i++;
+ while(i < signifLength && !sticky) {
+ currentDigit = getHexDigit(significandString,i);
+ sticky = sticky || (currentDigit != 0);
+ i++;
+ }
+
+ }
+ // else all of string was seen, round and sticky are
+ // correct as false.
+
+
+ // Check for overflow and update exponent accordingly.
+
+ if (exponent > Double.MAX_EXPONENT) { // Infinite result
+ // overflow to properly signed infinity
+ return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY);
+ } else { // Finite return value
+ if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result
+ exponent >= Double.MIN_EXPONENT) {
+
+ // The result returned in this block cannot be a
+ // zero or subnormal; however after the
+ // significand is adjusted from rounding, we could
+ // still overflow in infinity.
+
+ // AND exponent bits into significand; if the
+ // significand is incremented and overflows from
+ // rounding, this combination will update the
+ // exponent correctly, even in the case of
+ // Double.MAX_VALUE overflowing to infinity.
+
+ significand = (( (exponent +
+ (long)DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH-1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+ } else { // Subnormal or zero
+ // (exponent < Double.MIN_EXPONENT)
+
+ if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
+ // No way to round back to nonzero value
+ // regardless of significand if the exponent is
+ // less than -1075.
+ return new OldFloatingDecimalForTest(sign * 0.0);
+ } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+ /*
+ * Find bit position to round to; recompute
+ * round and sticky bits, and shift
+ * significand right appropriately.
+ */
+
+ sticky = sticky || round;
+ round = false;
+
+ // Number of bits of significand to preserve is
+ // exponent - abs_min_exp +1
+ // check:
+ // -1075 +1074 + 1 = 0
+ // -1023 +1074 + 1 = 52
+
+ int bitsDiscarded = 53 -
+ ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+ assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+ // What to do here:
+ // First, isolate the new round bit
+ round = (significand & (1L << (bitsDiscarded -1))) != 0L;
+ if (bitsDiscarded > 1) {
+ // create mask to update sticky bits; low
+ // order bitsDiscarded bits should be 1
+ long mask = ~((~0L) << (bitsDiscarded -1));
+ sticky = sticky || ((significand & mask) != 0L ) ;
+ }
+
+ // Now, discard the bits
+ significand = significand >> bitsDiscarded;
+
+ significand = (( ((long)(Double.MIN_EXPONENT -1) + // subnorm exp.
+ (long)DoubleConsts.EXP_BIAS) <<
+ (DoubleConsts.SIGNIFICAND_WIDTH-1))
+ & DoubleConsts.EXP_BIT_MASK) |
+ (DoubleConsts.SIGNIF_BIT_MASK & significand);
+ }
+ }
+
+ // The significand variable now contains the currently
+ // appropriate exponent bits too.
+
+ /*
+ * Determine if significand should be incremented;
+ * making this determination depends on the least
+ * significant bit and the round and sticky bits.
+ *
+ * Round to nearest even rounding table, adapted from
+ * table 4.7 in "Computer Arithmetic" by IsraelKoren.
+ * The digit to the left of the "decimal" point is the
+ * least significant bit, the digits to the right of
+ * the point are the round and sticky bits
+ *
+ * Number Round(x)
+ * x0.00 x0.
+ * x0.01 x0.
+ * x0.10 x0.
+ * x0.11 x1. = x0. +1
+ * x1.00 x1.
+ * x1.01 x1.
+ * x1.10 x1. + 1
+ * x1.11 x1. + 1
+ */
+ boolean incremented = false;
+ boolean leastZero = ((significand & 1L) == 0L);
+ if( ( leastZero && round && sticky ) ||
+ ((!leastZero) && round )) {
+ incremented = true;
+ significand++;
+ }
+
+ OldFloatingDecimalForTest fd = new OldFloatingDecimalForTest(Math.copySign(
+ Double.longBitsToDouble(significand),
+ sign));
+
+ /*
+ * Set roundingDir variable field of fd properly so
+ * that the input string can be properly rounded to a
+ * float value. There are two cases to consider:
+ *
+ * 1. rounding to double discards sticky bit
+ * information that would change the result of a float
+ * rounding (near halfway case between two floats)
+ *
+ * 2. rounding to double rounds up when rounding up
+ * would not occur when rounding to float.
+ *
+ * For former case only needs to be considered when
+ * the bits rounded away when casting to float are all
+ * zero; otherwise, float round bit is properly set
+ * and sticky will already be true.
+ *
+ * The lower exponent bound for the code below is the
+ * minimum (normalized) subnormal exponent - 1 since a
+ * value with that exponent can round up to the
+ * minimum subnormal value and the sticky bit
+ * information must be preserved (i.e. case 1).
+ */
+ if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
+ (exponent <= Float.MAX_EXPONENT ) ){
+ // Outside above exponent range, the float value
+ // will be zero or infinity.
+
+ /*
+ * If the low-order 28 bits of a rounded double
+ * significand are 0, the double could be a
+ * half-way case for a rounding to float. If the
+ * double value is a half-way case, the double
+ * significand may have to be modified to round
+ * the the right float value (see the stickyRound
+ * method). If the rounding to double has lost
+ * what would be float sticky bit information, the
+ * double significand must be incremented. If the
+ * double value's significand was itself
+ * incremented, the float value may end up too
+ * large so the increment should be undone.
+ */
+ if ((significand & 0xfffffffL) == 0x0L) {
+ // For negative values, the sign of the
+ // roundDir is the same as for positive values
+ // since adding 1 increasing the significand's
+ // magnitude and subtracting 1 decreases the
+ // significand's magnitude. If neither round
+ // nor sticky is true, the double value is
+ // exact and no adjustment is required for a
+ // proper float rounding.
+ if( round || sticky) {
+ if (leastZero) { // prerounding lsb is 0
+ // If round and sticky were both true,
+ // and the least significant
+ // significand bit were 0, the rounded
+ // significand would not have its
+ // low-order bits be zero. Therefore,
+ // we only need to adjust the
+ // significand if round XOR sticky is
+ // true.
+ if (round ^ sticky) {
+ fd.roundDir = 1;
+ }
+ }
+ else { // prerounding lsb is 1
+ // If the prerounding lsb is 1 and the
+ // resulting significand has its
+ // low-order bits zero, the significand
+ // was incremented. Here, we undo the
+ // increment, which will ensure the
+ // right guard and sticky bits for the
+ // float rounding.
+ if (round)
+ fd.roundDir = -1;
+ }
+ }
+ }
+ }
+
+ fd.fromHex = true;
+ return fd;
+ }
+ }
+ }
+
+ /**
+ * Return <code>s</code> with any leading zeros removed.
+ */
+ static String stripLeadingZeros(String s) {
+ return s.replaceFirst("^0+", "");
+ }
+
+ /**
+ * Extract a hexadecimal digit from position <code>position</code>
+ * of string <code>s</code>.
+ */
+ static int getHexDigit(String s, int position) {
+ int value = Character.digit(s.charAt(position), 16);
+ if (value <= -1 || value >= 16) {
+ throw new AssertionError("Unexpected failure of digit conversion of " +
+ s.charAt(position));
+ }
+ return value;
+ }
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/TestFDBigInteger.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.math.BigInteger;
+import java.util.Random;
+import jdk.internal.math.FDBigInteger;
+
+/**
+ * @test
+ * @bug 7032154
+ * @summary unit testys of FDBigInteger
+ * @modules java.base/jdk.internal.math
+ * @author Dmitry Nadezhin
+ */
+public class TestFDBigInteger {
+
+ private static final int MAX_P5 = 413;
+ private static final int MAX_P2 = 65;
+ private static final long LONG_SIGN_MASK = (1L << 63);
+ private static final BigInteger FIVE = BigInteger.valueOf(5);
+ private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
+ private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
+ private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
+ private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
+ private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
+
+ static {
+ IMMUTABLE_ZERO.makeImmutable();
+ IMMUTABLE_MILLION.makeImmutable();
+ IMMUTABLE_BILLION.makeImmutable();
+ IMMUTABLE_TEN18.makeImmutable();
+ }
+
+ private static FDBigInteger mutable(String hex, int offset) {
+ char[] chars = new BigInteger(hex, 16).toString().toCharArray();
+ return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
+ }
+
+ private static FDBigInteger immutable(String hex, int offset) {
+ FDBigInteger fd = mutable(hex, offset);
+ fd.makeImmutable();
+ return fd;
+ }
+
+ private static BigInteger biPow52(int p5, int p2) {
+ return FIVE.pow(p5).shiftLeft(p2);
+ }
+
+ // data.length == 1, nWords == 1, offset == 0
+ private static FDBigInteger genMillion1() {
+ return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
+ }
+
+ // data.length == 2, nWords == 1, offset == 0
+ private static FDBigInteger genMillion2() {
+ return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
+ }
+
+ // data.length == 1, nWords == 1, offset == 0
+ private static FDBigInteger genBillion1() {
+ return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
+ }
+
+ // data.length == 2, nWords == 2, offset == 0
+ private static FDBigInteger genTen18() {
+ return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
+ }
+
+ private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
+ if (!expected.equals(actual.toBigInteger())) {
+ throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
+ }
+ }
+
+ private static void testValueOfPow52(int p5, int p2) throws Exception {
+ check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
+ "valueOfPow52(" + p5 + "," + p2 + ")");
+ }
+
+ private static void testValueOfPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ testValueOfPow52(p5, p2);
+ }
+ }
+ }
+
+ private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
+ BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
+ if (value < 0) {
+ bi = bi.setBit(63);
+ }
+ check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
+ "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
+ }
+
+ private static void testValueOfMulPow52(long value, int p5) throws Exception {
+ testValueOfMulPow52(value, p5, 0);
+ testValueOfMulPow52(value, p5, 1);
+ testValueOfMulPow52(value, p5, 30);
+ testValueOfMulPow52(value, p5, 31);
+ testValueOfMulPow52(value, p5, 33);
+ testValueOfMulPow52(value, p5, 63);
+ }
+
+ private static void testValueOfMulPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ testValueOfMulPow52(0xFFFFFFFFL, p5);
+ testValueOfMulPow52(0x123456789AL, p5);
+ testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
+ testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
+ }
+ }
+
+ private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.leftShift(shift);
+ if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
+ throw new Exception("leftShift doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(bt, t, "leftShift corrupts its argument");
+ }
+ check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
+ }
+
+ private static void testLeftShift() throws Exception {
+ testLeftShift(IMMUTABLE_ZERO, 0, true);
+ testLeftShift(IMMUTABLE_ZERO, 10, true);
+ testLeftShift(MUTABLE_ZERO, 0, false);
+ testLeftShift(MUTABLE_ZERO, 10, false);
+
+ testLeftShift(IMMUTABLE_MILLION, 0, true);
+ testLeftShift(IMMUTABLE_MILLION, 1, true);
+ testLeftShift(IMMUTABLE_MILLION, 12, true);
+ testLeftShift(IMMUTABLE_MILLION, 13, true);
+ testLeftShift(IMMUTABLE_MILLION, 32, true);
+ testLeftShift(IMMUTABLE_MILLION, 33, true);
+ testLeftShift(IMMUTABLE_MILLION, 44, true);
+ testLeftShift(IMMUTABLE_MILLION, 45, true);
+
+ testLeftShift(genMillion1(), 0, false);
+ testLeftShift(genMillion1(), 1, false);
+ testLeftShift(genMillion1(), 12, false);
+ testLeftShift(genMillion1(), 13, false);
+ testLeftShift(genMillion1(), 25, false);
+ testLeftShift(genMillion1(), 26, false);
+ testLeftShift(genMillion1(), 32, false);
+ testLeftShift(genMillion1(), 33, false);
+ testLeftShift(genMillion1(), 44, false);
+ testLeftShift(genMillion1(), 45, false);
+
+ testLeftShift(genMillion2(), 0, false);
+ testLeftShift(genMillion2(), 1, false);
+ testLeftShift(genMillion2(), 12, false);
+ testLeftShift(genMillion2(), 13, false);
+ testLeftShift(genMillion2(), 25, false);
+ testLeftShift(genMillion2(), 26, false);
+ testLeftShift(genMillion2(), 32, false);
+ testLeftShift(genMillion2(), 33, false);
+ testLeftShift(genMillion2(), 44, false);
+ testLeftShift(genMillion2(), 45, false);
+ }
+
+ private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bs = s.toBigInteger();
+ int q = t.quoRemIteration(s);
+ BigInteger[] qr = bt.divideAndRemainder(bs);
+ if (!BigInteger.valueOf(q).equals(qr[0])) {
+ throw new Exception("quoRemIteration returns incorrect quo");
+ }
+ check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
+ }
+
+ private static void testQuoRemIteration() throws Exception {
+ // IMMUTABLE_TEN18 == 0de0b6b3a7640000
+ // q = 0
+ testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
+ // q = 1 -> q = 0
+ testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
+ // q = 1
+ testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
+ testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
+ // q = 18
+ testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
+ }
+
+ private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bo = o.toBigInteger();
+ int cmp = t.cmp(o);
+ int bcmp = bt.compareTo(bo);
+ if (bcmp != cmp) {
+ throw new Exception("cmp returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "cmp corrupts this");
+ check(bo, o, "cmp corrupts other");
+ if (o.cmp(t) != -cmp) {
+ throw new Exception("asymmetrical cmp");
+ }
+ check(bt, t, "cmp corrupts this");
+ check(bo, o, "cmp corrupts other");
+ }
+
+ private static void testCmp() throws Exception {
+ testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
+ testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
+ testCmp(mutable("5", 0), mutable("6", 0));
+ testCmp(mutable("5", 0), mutable("5", 0));
+ testCmp(mutable("5000000001", 0), mutable("500000001", 0));
+ testCmp(mutable("5000000001", 0), mutable("6", 1));
+ testCmp(mutable("5000000001", 0), mutable("5", 1));
+ testCmp(mutable("5000000000", 0), mutable("5", 1));
+ }
+
+ private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
+ FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
+ BigInteger bt = t.toBigInteger();
+ BigInteger bo = biPow52(p5, p2);
+ int cmp = t.cmp(o);
+ int bcmp = bt.compareTo(bo);
+ if (bcmp != cmp) {
+ throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "cmpPow52 corrupts this");
+ check(bo, o, "cmpPow5 corrupts other");
+ }
+
+ private static void testCmpPow52() throws Exception {
+ testCmpPow52(mutable("00000002", 1), 0, 31);
+ testCmpPow52(mutable("00000002", 1), 0, 32);
+ testCmpPow52(mutable("00000002", 1), 0, 33);
+ testCmpPow52(mutable("00000002", 1), 0, 34);
+ testCmpPow52(mutable("00000002", 1), 0, 64);
+ testCmpPow52(mutable("00000003", 1), 0, 32);
+ testCmpPow52(mutable("00000003", 1), 0, 33);
+ testCmpPow52(mutable("00000003", 1), 0, 34);
+ }
+
+ private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ BigInteger bx = x.toBigInteger();
+ BigInteger by = y.toBigInteger();
+ int cmp = t.addAndCmp(x, y);
+ int bcmp = bt.compareTo(bx.add(by));
+ if (bcmp != cmp) {
+ throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
+ }
+ check(bt, t, "addAndCmp corrupts this");
+ check(bx, x, "addAndCmp corrupts x");
+ check(by, y, "addAndCmp corrupts y");
+ }
+
+ private static void testAddAndCmp() throws Exception {
+ testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
+ testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
+ testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
+ testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
+ testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
+
+ testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
+ testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
+
+ testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+ testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
+
+ testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
+ testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
+ }
+
+ private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.multBy10();
+ if ((bt.signum() == 0 || !isImmutable) && r != t) {
+ throw new Exception("multBy10 of doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(bt, t, "multBy10 corrupts its argument");
+ }
+ check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
+ }
+
+ private static void testMultBy10() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ testMultBy10(value, false);
+ value.makeImmutable();
+ testMultBy10(value, true);
+ }
+ }
+ }
+
+ private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
+ BigInteger bt = t.toBigInteger();
+ FDBigInteger r = t.multByPow52(p5, p2);
+ if (bt.signum() == 0 && r != t) {
+ throw new Exception("multByPow52 of doesn't reuse its argument");
+ }
+ check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
+ }
+
+ private static void testMultByPow52() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ testMultByPow52(value, p5, p2);
+ }
+ }
+ }
+
+ private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
+ BigInteger biLeft = left.toBigInteger();
+ BigInteger biRight = right.toBigInteger();
+ FDBigInteger diff = left.leftInplaceSub(right);
+ if (!isImmutable && diff != left) {
+ throw new Exception("leftInplaceSub of doesn't reuse its argument");
+ }
+ if (isImmutable) {
+ check(biLeft, left, "leftInplaceSub corrupts its left immutable argument");
+ }
+ check(biRight, right, "leftInplaceSub corrupts its right argument");
+ check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
+ }
+
+ private static void testLeftInplaceSub() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+// for (int p5r = 0; p5r <= p5; p5r += 10) {
+// for (int p2r = 0; p2r <= p2; p2r += 10) {
+ for (int p5r = 0; p5r <= p5; p5r++) {
+ for (int p2r = 0; p2r <= p2; p2r++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ testLeftInplaceSub(left, right, false);
+ left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ left.makeImmutable();
+ testLeftInplaceSub(left, right, true);
+ }
+ }
+ }
+ }
+ }
+
+ private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
+ BigInteger biLeft = left.toBigInteger();
+ BigInteger biRight = right.toBigInteger();
+ FDBigInteger diff = left.rightInplaceSub(right);
+ if (!isImmutable && diff != right) {
+ throw new Exception("rightInplaceSub of doesn't reuse its argument");
+ }
+ check(biLeft, left, "leftInplaceSub corrupts its left argument");
+ if (isImmutable) {
+ check(biRight, right, "leftInplaceSub corrupts its right immutable argument");
+ }
+ try {
+ check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
+ } catch (Exception e) {
+ System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
+ throw e;
+ }
+ }
+
+ private static void testRightInplaceSub() throws Exception {
+ for (int p5 = 0; p5 <= MAX_P5; p5++) {
+ for (int p2 = 0; p2 <= MAX_P2; p2++) {
+// for (int p5r = 0; p5r <= p5; p5r += 10) {
+// for (int p2r = 0; p2r <= p2; p2r += 10) {
+ for (int p5r = 0; p5r <= p5; p5r++) {
+ for (int p2r = 0; p2r <= p2; p2r++) {
+ // This strange way of creating a value ensures that it is mutable.
+ FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
+ FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ testRightInplaceSub(left, right, false);
+ right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
+ right.makeImmutable();
+ testRightInplaceSub(left, right, true);
+ }
+ }
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ testValueOfPow52();
+ testValueOfMulPow52();
+ testLeftShift();
+ testQuoRemIteration();
+ testCmp();
+ testCmpPow52();
+ testAddAndCmp();
+ // Uncomment the following for more comprehensize but slow testing.
+ // testLeftInplaceSub();
+ // testMultBy10();
+ // testMultByPow52();
+ // testRightInplaceSub();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/math/FloatingDecimal/TestFloatingDecimal.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.Random;
+import jdk.internal.math.FloatingDecimal;
+
+/*
+OldFloatingDecimalForTest
+
+public class OldFloatingDecimalForTest {
+ public boolean digitsRoundedUp();
+ public OldFloatingDecimalForTest(double);
+ public OldFloatingDecimalForTest(float);
+ public boolean decimalDigitsExact();
+ public java.lang.String toString();
+ public java.lang.String toJavaFormatString();
+ public void appendTo(java.lang.Appendable);
+ public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException;
+ public strictfp double doubleValue();
+ public strictfp float floatValue();
+}
+
+jdk.internal.math.FloatingDecimal
+
+public class jdk.internal.math.FloatingDecimal {
+ public jdk.internal.math.FloatingDecimal();
+ public static java.lang.String toJavaFormatString(double);
+ public static java.lang.String toJavaFormatString(float);
+ public static void appendTo(double, java.lang.Appendable);
+ public static void appendTo(float, java.lang.Appendable);
+ public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
+ public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
+ public static jdk.internal.math.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
+}
+*/
+
+/**
+ * @test
+ * @bug 7032154
+ * @summary unit tests of FloatingDecimal
+ * @modules java.base/jdk.internal.math
+ * @library /java/lang/Math
+ * @build DoubleConsts FloatConsts
+ * @run main TestFloatingDecimal
+ * @author Brian Burkhalter
+ * @key randomness
+ */
+public class TestFloatingDecimal {
+ private static enum ResultType {
+ RESULT_EXCEPTION,
+ RESULT_PRINT
+ }
+
+ private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT;
+ private static final int NUM_RANDOM_TESTS = 100000;
+
+ private static final Random RANDOM = new Random();
+
+ private static void result(String message) {
+ switch (RESULT_TYPE) {
+ case RESULT_EXCEPTION:
+ throw new RuntimeException(message);
+ case RESULT_PRINT:
+ System.err.println(message);
+ break;
+ default:
+ assert false;
+ }
+ }
+
+ private static int check(String test, Object expected, Object actual) {
+ int failures = 0;
+ if(!actual.equals(expected)) {
+ failures++;
+ result("Test "+test+" expected "+expected+" but obtained "+actual);
+ }
+ return failures;
+ }
+
+ private static int testAppendToDouble() {
+ System.out.println(" testAppendToDouble");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ StringBuilder sb = new StringBuilder();
+ ofd.appendTo(sb);
+ String oldString = sb.toString();
+ sb = new StringBuilder();
+ FloatingDecimal.appendTo(d[j], sb);
+ String newString = sb.toString();
+ failures += check("testAppendToDouble", oldString, newString);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testAppendToFloat() {
+ System.out.println(" testAppendToFloat");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextLong(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ StringBuilder sb = new StringBuilder();
+ ofd.appendTo(sb);
+ String oldString = sb.toString();
+ sb = new StringBuilder();
+ FloatingDecimal.appendTo(f[j], sb);
+ String newString = sb.toString();
+ failures += check("testAppendToFloat", oldString, newString);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testAppendTo() {
+ System.out.println("testAppendTo");
+ int failures = 0;
+
+ failures += testAppendToDouble();
+ failures += testAppendToFloat();
+
+ return failures;
+ }
+
+ private static int testParseDouble() {
+ System.out.println(" testParseDouble");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ String javaFormatString = ofd.toJavaFormatString();
+ ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
+ double oldDouble = ofd.doubleValue();
+ double newDouble = FloatingDecimal.parseDouble(javaFormatString);
+ failures += check("testParseDouble", oldDouble, newDouble);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testParseFloat() {
+ System.out.println(" testParseFloat");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextInt(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ String javaFormatString = ofd.toJavaFormatString();
+ ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
+ float oldFloat = ofd.floatValue();
+ float newFloat = FloatingDecimal.parseFloat(javaFormatString);
+ failures += check("testParseFloat", oldFloat, newFloat);
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testParse() {
+ System.out.println("testParse");
+ int failures = 0;
+
+ failures += testParseDouble();
+ failures += testParseFloat();
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDoubleFixed() {
+ System.out.println(" testToJavaFormatStringDoubleFixed");
+ int failures = 0;
+
+ double[] d = new double [] {
+ -5.9522650387500933e18, // dtoa() fast path
+ 0.872989018674569, // dtoa() fast iterative - long
+ 1.1317400099603851e308 // dtoa() slow iterative
+ };
+
+ for(int i = 0; i < d.length; i++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]);
+ failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i]));
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDoubleRandom() {
+ System.out.println(" testToJavaFormatStringDoubleRandom");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ double[] d = new double[] {
+ RANDOM.nextLong(),
+ RANDOM.nextGaussian(),
+ RANDOM.nextDouble()*Double.MAX_VALUE
+ };
+ for(int j = 0; j < d.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
+ failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j]));
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringDouble() {
+ System.out.println(" testToJavaFormatStringDouble");
+ int failures = 0;
+ failures += testToJavaFormatStringDoubleFixed();
+ failures += testToJavaFormatStringDoubleRandom();
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloatFixed() {
+ System.out.println(" testToJavaFormatStringFloatFixed");
+ int failures = 0;
+
+ float[] f = new float[] {
+ -9.8784166e8f, // dtoa() fast path
+ 0.70443946f, // dtoa() fast iterative - int
+ 1.8254228e37f // dtoa() slow iterative
+ };
+
+ for(int i = 0; i < f.length; i++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]);
+ failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i]));
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloatRandom() {
+ System.out.println(" testToJavaFormatStringFloatRandom");
+ int failures = 0;
+
+ for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
+ float[] f = new float[] {
+ RANDOM.nextInt(),
+ (float)RANDOM.nextGaussian(),
+ RANDOM.nextFloat()*Float.MAX_VALUE
+ };
+ for(int j = 0; j < f.length; j++) {
+ OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
+ failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j]));
+ }
+ }
+
+ return failures;
+ }
+
+ private static int testToJavaFormatStringFloat() {
+ System.out.println(" testToJavaFormatStringFloat");
+ int failures = 0;
+
+ failures += testToJavaFormatStringFloatFixed();
+ failures += testToJavaFormatStringFloatRandom();
+
+ return failures;
+ }
+
+ private static int testToJavaFormatString() {
+ System.out.println("testToJavaFormatString");
+ int failures = 0;
+
+ failures += testToJavaFormatStringDouble();
+ failures += testToJavaFormatStringFloat();
+
+ return failures;
+ }
+
+ public static void main(String[] args) {
+ int failures = 0;
+
+ failures += testAppendTo();
+ failures += testParse();
+ failures += testToJavaFormatString();
+
+ if (failures != 0) {
+ throw new RuntimeException("" + failures + " failures while testing FloatingDecimal");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8144355
+ * @summary Test aliasing additions to ZipFileSystem for multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarTest
+ */
+
+import java.io.IOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.net.URI;
+import java.nio.file.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static sun.misc.Version.jdkMajorVersion;
+
+import org.testng.Assert;
+import org.testng.annotations.*;
+
+public class MultiReleaseJarTest {
+ final private String userdir = System.getProperty("user.dir",".");
+ final private Map<String,String> stringEnv = new HashMap<>();
+ final private Map<String,Integer> integerEnv = new HashMap<>();
+ final private String className = "version.Version";
+ final private MethodType mt = MethodType.methodType(int.class);
+
+ private String entryName;
+ private URI uvuri;
+ private URI mruri;
+ private URI smruri;
+
+ @BeforeClass
+ public void initialize() throws Exception {
+ CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+ creator.compileEntries();
+ creator.buildUnversionedJar();
+ creator.buildMultiReleaseJar();
+ creator.buildShortMultiReleaseJar();
+ String ssp = Paths.get(userdir, "unversioned.jar").toUri().toString();
+ uvuri = new URI("jar", ssp , null);
+ ssp = Paths.get(userdir, "multi-release.jar").toUri().toString();
+ mruri = new URI("jar", ssp, null);
+ ssp = Paths.get(userdir, "short-multi-release.jar").toUri().toString();
+ smruri = new URI("jar", ssp, null);
+ entryName = className.replace('.', '/') + ".class";
+ }
+
+ public void close() throws IOException {
+ Files.delete(Paths.get(userdir, "unversioned.jar"));
+ Files.delete(Paths.get(userdir, "multi-release.jar"));
+ Files.delete(Paths.get(userdir, "short-multi-release.jar"));
+ }
+
+ @DataProvider(name="strings")
+ public Object[][] createStrings() {
+ return new Object[][]{
+ {"runtime", jdkMajorVersion()},
+ {"-20", 8},
+ {"0", 8},
+ {"8", 8},
+ {"9", 9},
+ {"10", 10},
+ {"11", 10},
+ {"50", 10}
+ };
+ }
+
+ @DataProvider(name="integers")
+ public Object[][] createIntegers() {
+ return new Object[][] {
+ {new Integer(-5), 8},
+ {new Integer(0), 8},
+ {new Integer(8), 8},
+ {new Integer(9), 9},
+ {new Integer(10), 10},
+ {new Integer(11), 10},
+ {new Integer(100), 10}
+ };
+ }
+
+ // Not the best test but all I can do since ZipFileSystem and JarFileSystem
+ // are not public, so I can't use (fs instanceof ...)
+ @Test
+ public void testNewFileSystem() throws Exception {
+ Map<String,String> env = new HashMap<>();
+ // no configuration, treat multi-release jar as unversioned
+ try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
+ Assert.assertTrue(readAndCompare(fs, 8));
+ }
+ env.put("multi-release", "runtime");
+ // a configuration and jar file is multi-release
+ try (FileSystem fs = FileSystems.newFileSystem(mruri, env)) {
+ Assert.assertTrue(readAndCompare(fs, jdkMajorVersion()));
+ }
+ // a configuration but jar file is unversioned
+ try (FileSystem fs = FileSystems.newFileSystem(uvuri, env)) {
+ Assert.assertTrue(readAndCompare(fs, 8));
+ }
+ }
+
+ private boolean readAndCompare(FileSystem fs, int expected) throws IOException {
+ Path path = fs.getPath("version/Version.java");
+ String src = new String(Files.readAllBytes(path));
+ return src.contains("return " + expected);
+ }
+
+ @Test(dataProvider="strings")
+ public void testStrings(String value, int expected) throws Throwable {
+ stringEnv.put("multi-release", value);
+ runTest(stringEnv, expected);
+ }
+
+ @Test(dataProvider="integers")
+ public void testIntegers(Integer value, int expected) throws Throwable {
+ integerEnv.put("multi-release", value);
+ runTest(integerEnv, expected);
+ }
+
+ @Test
+ public void testShortJar() throws Throwable {
+ integerEnv.put("multi-release", Integer.valueOf(10));
+ runTest(smruri, integerEnv, 10);
+ integerEnv.put("multi-release", Integer.valueOf(9));
+ runTest(smruri, integerEnv, 8);
+ }
+
+ private void runTest(Map<String,?> env, int expected) throws Throwable {
+ runTest(mruri, env, expected);
+ }
+
+ private void runTest(URI uri, Map<String,?> env, int expected) throws Throwable {
+ try (FileSystem fs = FileSystems.newFileSystem(uri, env)) {
+ Path version = fs.getPath(entryName);
+ byte [] bytes = Files.readAllBytes(version);
+ Class<?> vcls = (new ByteArrayClassLoader(fs)).defineClass(className, bytes);
+ MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+ Assert.assertEquals((int)mh.invoke(vcls.newInstance()), expected);
+ }
+ }
+
+ private static class ByteArrayClassLoader extends ClassLoader {
+ final private FileSystem fs;
+
+ ByteArrayClassLoader(FileSystem fs) {
+ super(null);
+ this.fs = fs;
+ }
+
+ @Override
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ try {
+ return super.loadClass(name);
+ } catch (ClassNotFoundException x) {}
+ Path cls = fs.getPath(name.replace('.', '/') + ".class");
+ try {
+ byte[] bytes = Files.readAllBytes(cls);
+ return defineClass(name, bytes);
+ } catch (IOException x) {
+ throw new ClassNotFoundException(x.getMessage());
+ }
+ }
+
+ public Class<?> defineClass(String name, byte[] bytes) throws ClassNotFoundException {
+ if (bytes == null) throw new ClassNotFoundException("No bytes for " + name);
+ return defineClass(name, bytes, 0, bytes.length);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/java/util/jar/Compiler.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,120 @@
+/*
+ * 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 javax.tools.*;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+class Compiler {
+ final private Map<String,String> input;
+ private List<String> options;
+
+ Compiler(Map<String,String> input) {
+ this.input = input;
+ }
+
+ Compiler setRelease(int release) {
+ // Setting the -release option does not work for some reason
+ // so do it the old fashioned way
+ // options = Arrays.asList("-release", String.valueOf(release));
+ String target = String.valueOf(release);
+ options = Arrays.asList("-source", target, "-target", target);
+ return this;
+ }
+
+ Map<String,byte[]> compile() {
+ List<SourceFileObject> cunits = createCompilationUnits();
+ Map<String,ClassFileObject> cfos = createClassFileObjects();
+ JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
+ JavaFileManager jfm = new CustomFileManager(jc.getStandardFileManager(null, null, null), cfos);
+ jc.getTask(null, jfm, null, options, null, cunits).call();
+ return createOutput(cfos);
+ }
+
+ private List<SourceFileObject> createCompilationUnits() {
+ return input.entrySet().stream()
+ .map(e -> new SourceFileObject(e.getKey(), e.getValue())).collect(Collectors.toList());
+ }
+
+ private Map<String,ClassFileObject> createClassFileObjects() {
+ return input.keySet().stream()
+ .collect(Collectors.toMap(k -> k, k -> new ClassFileObject(k)));
+ }
+
+ private Map<String,byte[]> createOutput(Map<String,ClassFileObject> cfos) {
+ return cfos.keySet().stream().collect(Collectors.toMap(k -> k, k -> cfos.get(k).getBytes()));
+ }
+
+ private static class SourceFileObject extends SimpleJavaFileObject {
+ private final String source;
+
+ SourceFileObject(String name, String source) {
+ super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
+ this.source = source;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return source;
+ }
+ }
+
+ private static class ClassFileObject extends SimpleJavaFileObject {
+ private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ ClassFileObject(String className) {
+ super(URI.create(className), Kind.CLASS);
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return baos;
+ }
+
+ public byte[] getBytes() {
+ return baos.toByteArray();
+ }
+ }
+
+ private static class CustomFileManager extends ForwardingJavaFileManager<JavaFileManager> {
+ private final Map<String,ClassFileObject> cfos;
+
+ CustomFileManager(JavaFileManager jfm, Map<String,ClassFileObject> cfos) {
+ super(jfm);
+ this.cfos = cfos;
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(JavaFileManager.Location loc, String name,
+ JavaFileObject.Kind kind, FileObject sibling) throws IOException {
+ ClassFileObject cfo = cfos.get(name);
+ return cfo;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/java/util/jar/CreateMultiReleaseTestJars.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,160 @@
+/*
+ * 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.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+
+public class CreateMultiReleaseTestJars {
+ final private String main =
+ "package version;\n\n"
+ + "public class Main {\n"
+ + " public static void main(String[] args) {\n"
+ + " Version v = new Version();\n"
+ + " System.out.println(\"I am running on version \" + v.getVersion());\n"
+ + " }\n"
+ + "}\n";
+ final private String java8 =
+ "package version;\n\n"
+ + "public class Version {\n"
+ + " public int getVersion() {\n"
+ + " return 8;\n"
+ + " }\n"
+ + "}\n";
+ final private String java9 =
+ "package version;\n\n"
+ + "public class Version {\n"
+ + " public int getVersion() {\n"
+ + " int version = (new PackagePrivate()).getVersion();\n"
+ + " if (version == 9) return 9;\n" // strange I know, but easy to test
+ + " return version;\n"
+ + " }\n"
+ + "}\n";
+ final private String ppjava9 =
+ "package version;\n\n"
+ + "class PackagePrivate {\n"
+ + " int getVersion() {\n"
+ + " return 9;\n"
+ + " }\n"
+ + "}\n";
+ final private String java10 = java8.replace("8", "10");
+ final String readme8 = "This is the root readme file";
+ final String readme9 = "This is the version nine readme file";
+ final String readme10 = "This is the version ten readme file";
+ private Map<String,byte[]> rootClasses;
+ private Map<String,byte[]> version9Classes;
+ private Map<String,byte[]> version10Classes;
+
+ public void buildUnversionedJar() throws IOException {
+ JarBuilder jb = new JarBuilder("unversioned.jar");
+ jb.addEntry("README", readme8.getBytes());
+ jb.addEntry("version/Main.java", main.getBytes());
+ jb.addEntry("version/Main.class", rootClasses.get("version.Main"));
+ jb.addEntry("version/Version.java", java8.getBytes());
+ jb.addEntry("version/Version.class", rootClasses.get("version.Version"));
+ jb.build();
+ }
+
+ public void buildMultiReleaseJar() throws IOException {
+ JarBuilder jb = new JarBuilder("multi-release.jar");
+ jb.addAttribute("Multi-Release", "true");
+ jb.addEntry("README", readme8.getBytes());
+ jb.addEntry("version/Main.java", main.getBytes());
+ jb.addEntry("version/Main.class", rootClasses.get("version.Main"));
+ jb.addEntry("version/Version.java", java8.getBytes());
+ jb.addEntry("version/Version.class", rootClasses.get("version.Version"));
+ jb.addEntry("META-INF/versions/9/README", readme9.getBytes());
+ jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes());
+ jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes());
+ jb.addEntry("META-INF/versions/9/version/Version.class", version9Classes.get("version.Version"));
+ jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate"));
+ jb.addEntry("META-INF/versions/10/README", readme10.getBytes());
+ jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes());
+ jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version"));
+ jb.build();
+ }
+
+ public void buildShortMultiReleaseJar() throws IOException {
+ JarBuilder jb = new JarBuilder("short-multi-release.jar");
+ jb.addAttribute("Multi-Release", "true");
+ jb.addEntry("README", readme8.getBytes());
+ jb.addEntry("version/Main.java", main.getBytes());
+ jb.addEntry("version/Main.class", rootClasses.get("version.Main"));
+ jb.addEntry("version/Version.java", java8.getBytes());
+ jb.addEntry("version/Version.class", rootClasses.get("version.Version"));
+ jb.addEntry("META-INF/versions/9/README", readme9.getBytes());
+ jb.addEntry("META-INF/versions/9/version/Version.java", java9.getBytes());
+ jb.addEntry("META-INF/versions/9/version/PackagePrivate.java", ppjava9.getBytes());
+ // no entry for META-INF/versions/9/version/Version.class
+ jb.addEntry("META-INF/versions/9/version/PackagePrivate.class", version9Classes.get("version.PackagePrivate"));
+ jb.addEntry("META-INF/versions/10/README", readme10.getBytes());
+ jb.addEntry("META-INF/versions/10/version/Version.java", java10.getBytes());
+ jb.addEntry("META-INF/versions/10/version/Version.class", version10Classes.get("version.Version"));
+ jb.build();
+ }
+
+ public void buildSignedMultiReleaseJar() throws Exception {
+ String testsrc = System.getProperty("test.src",".");
+ String testdir = findTestDir(testsrc);
+ String keystore = testdir + "/sun/security/tools/jarsigner/JarSigning.keystore";
+ String[] jsArgs = {
+ "-keystore", keystore,
+ "-storepass", "bbbbbb",
+ "-signedJar", "signed-multi-release.jar",
+ "multi-release.jar", "b"
+ };
+ sun.security.tools.jarsigner.Main.main(jsArgs);
+
+ }
+
+ String findTestDir(String dir) throws IOException {
+ Path path = Paths.get(dir).toAbsolutePath();
+ while (path != null && !path.endsWith("test")) {
+ path = path.getParent();
+ }
+ if (path == null) {
+ throw new IllegalArgumentException(dir + " is not in a test directory");
+ }
+ if (!Files.isDirectory(path)) {
+ throw new IOException(path.toString() + " is not a directory");
+ }
+ return path.toString();
+ }
+
+ void compileEntries() {
+ Map<String,String> input = new HashMap<>();
+ input.put("version.Main", main);
+ input.put("version.Version", java8);
+ rootClasses = (new Compiler(input)).setRelease(8).compile();
+ input.clear();
+ input.put("version.Version", java9);
+ input.put("version.PackagePrivate", ppjava9);
+ version9Classes = (new Compiler(input)).setRelease(9).compile();
+ input.clear();
+ input.put("version.Version", java10);
+ version10Classes = (new Compiler(input)).setRelease(9).compile(); // fixme in JDK 10
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/lib/testlibrary/java/util/jar/JarBuilder.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,105 @@
+/*
+ * 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.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+public class JarBuilder {
+ final private String name;
+ final private Attributes attributes = new Attributes();
+ final private List<Entry> entries = new ArrayList<>();
+
+ public JarBuilder(String name) {
+ this.name = name;
+ attributes.putValue("Manifest-Version", "1.0");
+ attributes.putValue("Created-By", "1.9.0-internal (Oracle Corporation)");
+ }
+
+ public JarBuilder addAttribute(String name, String value) {
+ attributes.putValue(name, value);
+ return this;
+ }
+
+ public JarBuilder addEntry(String name, byte[] bytes) {
+ entries.add(new Entry(name, bytes));
+ return this;
+ }
+
+ public void build() throws IOException {
+ try (OutputStream os = Files.newOutputStream(Paths.get(name));
+ JarOutputStream jos = new JarOutputStream(os)) {
+ JarEntry me = new JarEntry("META-INF/MANIFEST.MF");
+ jos.putNextEntry(me);
+ Manifest manifest = new Manifest();
+ manifest.getMainAttributes().putAll(attributes);
+ manifest.write(jos);
+ jos.closeEntry();
+ entries.forEach(e -> {
+ JarEntry je = new JarEntry(e.name);
+ try {
+ jos.putNextEntry(je);
+ jos.write(e.bytes);
+ jos.closeEntry();
+ } catch (IOException iox) {
+ throw new RuntimeException(iox);
+ }
+ });
+ } catch (RuntimeException x) {
+ Throwable t = x.getCause();
+ if (t instanceof IOException) {
+ IOException iox = (IOException)t;
+ throw iox;
+ }
+ throw x;
+ }
+ }
+
+ private static class Entry {
+ String name;
+ byte[] bytes;
+
+ Entry(String name, byte[] bytes) {
+ this.name = name;
+ this.bytes = bytes;
+ }
+ }
+
+ public static void main(String[] args) throws IOException {
+ JarBuilder jb = new JarBuilder("version.jar");
+ jb.addAttribute("Multi-Release", "true");
+ String s = "something to say";
+ byte[] bytes = s.getBytes();
+ jb.addEntry("version/Version.class", bytes);
+ jb.addEntry("README", bytes);
+ jb.addEntry("version/Version.java", bytes);
+ jb.build();
+ }
+}
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Asserts.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,7 +42,11 @@
* multiple times, then the line number won't provide enough context to
* understand the failure.
* </pre>
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public class Asserts {
/**
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolFinder.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,6 +27,11 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
+ */
+@Deprecated
public final class JDKToolFinder {
private JDKToolFinder() {
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/JDKToolLauncher.java Wed Jan 06 14:54:24 2016 +0000
@@ -46,7 +46,10 @@
* Process p = pb.start();
* }
* </pre>
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public class JDKToolLauncher {
private final String executable;
private final List<String> vmArgs = new ArrayList<String>();
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputAnalyzer.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,12 @@
/**
* Utility class for verifying output and exit value from a {@code Process}.
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ *
*/
+@Deprecated
public final class OutputAnalyzer {
private final OutputBuffer output;
private final String stdout;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/OutputBuffer.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,6 +28,11 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
class OutputBuffer {
private static class OutputBufferException extends RuntimeException {
private static final long serialVersionUID = 8528687792643129571L;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Platform.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,6 +27,11 @@
import java.io.FileNotFoundException;
import java.io.IOException;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
+ */
+@Deprecated
public class Platform {
private static final String osName = System.getProperty("os.name");
private static final String dataModel = System.getProperty("sun.arch.data.model");
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/ProcessTools.java Wed Jan 06 14:54:24 2016 +0000
@@ -27,8 +27,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -42,6 +40,12 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;
+
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
public final class ProcessTools {
private static final class LineForwarder extends StreamPumper.LinePump {
private final PrintStream ps;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/StreamPumper.java Wed Jan 06 14:54:24 2016 +0000
@@ -34,6 +34,11 @@
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
+/**
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib/process}
+ */
+@Deprecated
public final class StreamPumper implements Runnable {
private static final int BUF_SIZE = 256;
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/Utils.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,11 @@
/**
* Common library for various test helper functions.
+ *
+ * @deprecated This class is deprecated. Use the one from
+ * {@code <root>/test/lib/share/classes/jdk/test/lib}
*/
+@Deprecated
public final class Utils {
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/marlin/ArrayCacheSizeTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,131 @@
+/*
+ * 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 sun.java2d.marlin.ArrayCache;
+
+/**
+ * @test
+ * @bug 8144445
+ * @summary Check the ArrayCache getNewLargeSize() method
+ * @run main ArrayCacheSizeTest
+ */
+public class ArrayCacheSizeTest {
+
+ public static void main(String[] args) {
+ testNewSize();
+ testNewLargeSize();
+ }
+
+ private static void testNewSize() {
+ testNewSize(0, 1);
+ testNewSize(0, 100000);
+
+ testNewSize(4096, 4097);
+ testNewSize(4096 * 16, 4096 * 16 + 1);
+
+ testNewSize(4096 * 4096 * 4, 4096 * 4096 * 4 + 1);
+
+ testNewSize(4096 * 4096 * 4, Integer.MAX_VALUE);
+
+ testNewSize(Integer.MAX_VALUE - 1000, Integer.MAX_VALUE);
+
+ testNewSizeExpectAIOB(Integer.MAX_VALUE - 1000, Integer.MAX_VALUE + 1);
+ testNewSizeExpectAIOB(1, -1);
+ testNewSizeExpectAIOB(Integer.MAX_VALUE, -1);
+ }
+
+ private static void testNewSizeExpectAIOB(final int curSize,
+ final int needSize) {
+ try {
+ testNewSize(curSize, needSize);
+ throw new RuntimeException("ArrayIndexOutOfBoundsException not thrown");
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
+ System.out.println("ArrayIndexOutOfBoundsException expected.");
+ } catch (RuntimeException re) {
+ throw re;
+ } catch (Throwable th) {
+ throw new RuntimeException("Unexpected exception", th);
+ }
+ }
+
+ private static void testNewSize(final int curSize,
+ final int needSize) {
+
+ int size = ArrayCache.getNewSize(curSize, needSize);
+
+ System.out.println("getNewSize(" + curSize + ", " + needSize
+ + ") = " + size);
+
+ if (size < 0 || size < needSize) {
+ throw new IllegalStateException("Invalid getNewSize("
+ + curSize + ", " + needSize + ") = " + size + " !");
+ }
+ }
+
+ private static void testNewLargeSize() {
+ testNewLargeSize(0, 1);
+ testNewLargeSize(0, 100000);
+
+ testNewLargeSize(4096, 4097);
+ testNewLargeSize(4096 * 16, 4096 * 16 + 1);
+
+ testNewLargeSize(4096 * 4096 * 4, 4096 * 4096 * 4 + 1);
+
+ testNewLargeSize(4096 * 4096 * 4, Integer.MAX_VALUE);
+
+ testNewLargeSize(Integer.MAX_VALUE - 1000, Integer.MAX_VALUE);
+
+ testNewLargeSizeExpectAIOB(Integer.MAX_VALUE - 1000, Integer.MAX_VALUE + 1L);
+ testNewLargeSizeExpectAIOB(1, -1L);
+ testNewLargeSizeExpectAIOB(Integer.MAX_VALUE, -1L);
+ }
+
+ private static void testNewLargeSizeExpectAIOB(final long curSize,
+ final long needSize) {
+ try {
+ testNewLargeSize(curSize, needSize);
+ throw new RuntimeException("ArrayIndexOutOfBoundsException not thrown");
+ } catch (ArrayIndexOutOfBoundsException aiobe) {
+ System.out.println("ArrayIndexOutOfBoundsException expected.");
+ } catch (RuntimeException re) {
+ throw re;
+ } catch (Throwable th) {
+ throw new RuntimeException("Unexpected exception", th);
+ }
+ }
+
+ private static void testNewLargeSize(final long curSize,
+ final long needSize) {
+
+ long size = ArrayCache.getNewLargeSize(curSize, needSize);
+
+ System.out.println("getNewLargeSize(" + curSize + ", " + needSize
+ + ") = " + size);
+
+ if (size < 0 || size < needSize || size > Integer.MAX_VALUE) {
+ throw new IllegalStateException("Invalid getNewLargeSize("
+ + curSize + ", " + needSize + ") = " + size + " !");
+ }
+ }
+
+}
--- a/jdk/test/sun/java2d/marlin/CrashTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/java2d/marlin/CrashTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,31 +31,44 @@
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
-import sun.java2d.pipe.RenderingEngine;
/**
- * Simple crash rendering test using huge GeneralPaths with marlin renderer
- *
- * run it with large heap (2g):
- * java -Dsun.java2d.renderer=sun.java2d.marlin.MarlinRenderingEngine marlin.CrashTest
- *
- * @author bourgesl
- */
+ * @test
+ * @summary Simple crash rendering test using huge GeneralPaths with the Marlin renderer
+ * @run main/othervm -mx512m CrashTest
+ * @ignore tests that take a long time and consumes 5Gb memory
+ * @run main/othervm -ms4g -mx4g CrashTest -slow
+*/
public class CrashTest {
static final boolean SAVE_IMAGE = false;
static boolean USE_ROUND_CAPS_AND_JOINS = true;
public static void main(String[] args) {
+ boolean runSlowTests = (args.length != 0 && "-slow".equals(args[0]));
+
+ // First display which renderer is tested:
+ System.setProperty("sun.java2d.renderer.verbose", "true");
+
// try insane image sizes:
// subpixel coords may overflow:
-// testHugeImage((Integer.MAX_VALUE >> 3) + 1, 6);
+ // check MAX_VALUE / (8 * 2); overflow may happen due to orientation flag
+ // But as it is impossible to allocate an image larger than 2Gb (byte) then
+ // it is also impossible to have rowAAChunk larger than 2Gb !
+
+ // Disabled test as it consumes 4GB heap + offheap (2Gb) ie > 6Gb !
+ if (runSlowTests) {
+ testHugeImage((Integer.MAX_VALUE >> 4) - 100, 16);
+ }
+
// larger than 23 bits: (RLE)
testHugeImage(8388608 + 1, 10);
- test(0.1f, false, 0);
- test(0.1f, true, 7f);
+ if (runSlowTests) {
+ test(0.1f, false, 0);
+ test(0.1f, true, 7f);
+ }
// Exceed 2Gb OffHeap buffer for edges:
try {
@@ -67,17 +80,15 @@
if (th instanceof ArrayIndexOutOfBoundsException) {
System.out.println("ArrayIndexOutOfBoundsException expected.");
} else {
- System.out.println("Exception occured:");
- th.printStackTrace();
+ throw new RuntimeException("Unexpected exception", th);
}
}
-
}
private static void test(final float lineStroke,
final boolean useDashes,
final float dashMinLen)
- throws ArrayIndexOutOfBoundsException
+ throws ArrayIndexOutOfBoundsException
{
System.out.println("---\n" + "test: "
+ "lineStroke=" + lineStroke
@@ -85,9 +96,6 @@
+", dashMinLen=" + dashMinLen
);
- final String renderer = RenderingEngine.getInstance().getClass().getSimpleName();
- System.out.println("Testing renderer = " + renderer);
-
final BasicStroke stroke = createStroke(lineStroke, useDashes, dashMinLen);
// TODO: test Dasher.firstSegmentsBuffer resizing ?
@@ -135,7 +143,7 @@
if (SAVE_IMAGE) {
try {
- final File file = new File("CrashTest-" + renderer + "-dash-" + useDashes + ".bmp");
+ final File file = new File("CrashTest-dash-" + useDashes + ".bmp");
System.out.println("Writing file: " + file.getAbsolutePath());
ImageIO.write(image, "BMP", file);
@@ -150,15 +158,10 @@
}
private static void testHugeImage(final int width, final int height)
- throws ArrayIndexOutOfBoundsException
+ throws ArrayIndexOutOfBoundsException
{
System.out.println("---\n" + "testHugeImage: "
- + "width=" + width
- + ", height=" + height
- );
-
- final String renderer = RenderingEngine.getInstance().getClass().getSimpleName();
- System.out.println("Testing renderer = " + renderer);
+ + "width=" + width + ", height=" + height);
final BasicStroke stroke = createStroke(2.5f, false, 0);
@@ -195,8 +198,8 @@
if (SAVE_IMAGE) {
try {
- final File file = new File("CrashTest-" + renderer +
- "-huge-" + width + "x" +height + ".bmp");
+ final File file = new File("CrashTest-huge-"
+ + width + "x" +height + ".bmp");
System.out.println("Writing file: " + file.getAbsolutePath());
ImageIO.write(image, "BMP", file);
--- a/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/management/jmxremote/startstop/JMXStartStopTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -58,7 +58,7 @@
* @run main/othervm/timeout=600 -XX:+UsePerfData JMXStartStopTest
* @summary Makes sure that enabling/disabling the management agent through JCMD
* achieves the desired results
- * @key randomness
+ * @key randomness intermittent
*/
public class JMXStartStopTest {
private static final String TEST_APP_NAME = "TestApp";
--- a/jdk/test/sun/misc/Encode/DecodeBuffer.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2000, 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 4159554
- * @summary Problem with UUDecoder
- * @modules java.base/sun.misc
- */
-
-import sun.misc.*;
-import java.io.*;
-
-public class DecodeBuffer {
-
- public static void main(String[] args) throws Exception {
- String encoded;
- // text to encode and decode
- String originalText = "Hi There, please encode and decode me";
- UUDecoder uuD = new UUDecoder();
-
- encoded = "begin 644 encoder.buf\r\n" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\r\n"+
- " \r\nend\r\n";
- check (uuD, encoded, originalText);
-
- encoded = "begin 644 encoder.buf\n" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\n"+
- " \nend\n";
- check (uuD, encoded, originalText);
-
- encoded = "begin 644 encoder.buf\r" +
- "E2&D@5&AE<F4L('!L96%S92!E;F-O9&4@86YD(&1E8V]D92!M90$!\r"+
- " \rend\r";
- check (uuD, encoded, originalText);
-
- // Multi-line Unix text file
-
- String s1 = "begin 644 f\n"+
- "M3W)I9VYL(\"I(:2!4:&5R92P@<&QE87-E(&5N8V]D92!A;F0@9&5C;V1E(&UE\n"+
- "M*@IA;F0@;64@06YD($UE(&%N1\"!M92!!;F0@344@04Y$($U%(%I80U8@,3(S\n"+
- "-97)T\"E5)3U @45=%\"DUE\n"+
- " \nend\n";
-
- String s2 = "Orignl *Hi There, please encode and decode me*\n"+
- "and me And Me anD me And ME AND ME ZXCV 123ert\n"+
- "UIOP QWE\n";
- check (uuD, s1, s2);
-
- // Multi-line Windows text file
-
- s1 = "begin 644 f\n"+
- "M2&5L;&\\@22!A;2!A(&UU;'1I;&EN92!F:6QE#0IC<F5A=&5D(&]N(%=I;F1O\r\n"+
- "M=W,L('1O('1E<W0@=&AE(%5516YC;V1E<@T*86YD(%551&5C;V1E<B!C;&%S\r\n"+
- "$<V5S+G1O\r\n"+ " \r\nend\r\n";
- s2="Hello I am a multiline file\r\n"+
- "created on Windows, to test the UUEncoder\r\n"+
- "and UUDecoder classes.";
- check (uuD, s1, s2);
- }
-
- public static void check (UUDecoder uuD, String s, String original) throws Exception {
- String decoded;
- // do UU stuff
- decoded = new String(uuD.decodeBuffer(s));
- if (!decoded.equals (original)) {
- throw new Exception ("decoded text not same as original");
- }
- }
-}
--- a/jdk/test/sun/misc/Encode/Encode.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 1998, 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 4041231
- * @summary Test UUEncoder.java for proper masking in encodeAtom
- * @modules java.base/sun.misc
- */
-
-import sun.misc.*;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-
-public class Encode {
-
- public static void main(String[] args) throws Exception {
- UUEncoder encoder = new UUEncoder("encode.buf");
- byte[] buffer = new byte[3];
-
- buffer[0] = -1;
- buffer[1] = -1;
- buffer[2] = -1;
-
- ByteArrayInputStream in = new ByteArrayInputStream(buffer);
- ByteArrayOutputStream out = new ByteArrayOutputStream(10);
-
- encoder.encodeBuffer(in, out);
- byte[] result = out.toByteArray();
-
- if (result[22] == 31)
- throw new RuntimeException("UUEncoder generates incorrect byte sequences in encodeAtom.");
-
- }
-}
--- a/jdk/test/sun/misc/Encode/GetBytes.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * Copyright (c) 2004, 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 5031097
- * @summary sun.misc.CharacterEncoder(ByteBuffer) is dumping too
- * much information
- * @modules java.base/sun.misc
- * @author Brad Wetmore
- */
-
-import java.nio.*;
-import sun.misc.*;
-
-public class GetBytes {
-
- public static void main(String args[]) throws Exception {
-
- ByteBuffer bb = ByteBuffer.wrap(new byte [26 + 2]);
-
- for (int i = 'a'; i < 'a' + bb.capacity(); i++) {
- bb.put((byte)i);
- }
-
- /*
- * Slice a subbuffer out of the original buffer.
- */
- bb.position(1);
- bb.limit(bb.capacity() - 1);
-
- ByteBuffer src = bb.slice();
-
- CharacterEncoder e = new BASE64Encoder();
- CharacterDecoder d = new BASE64Decoder();
-
- String encoded = e.encodeBuffer(src);
- ByteBuffer dst = d.decodeBufferToByteBuffer(encoded);
-
- src.rewind();
- dst.rewind();
-
- if (src.compareTo(dst) != 0) {
- throw new Exception("Didn't encode/decode correctly");
- }
- }
-}
--- a/jdk/test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,491 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//package sun.misc;
-
-/*
- * A really, really simple bigint package
- * tailored to the needs of floating base conversion.
- */
-class OldFDBigIntForTest {
- int nWords; // number of words used
- int data[]; // value: data[0] is least significant
-
-
- public OldFDBigIntForTest( int v ){
- nWords = 1;
- data = new int[1];
- data[0] = v;
- }
-
- public OldFDBigIntForTest( long v ){
- data = new int[2];
- data[0] = (int)v;
- data[1] = (int)(v>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- }
-
- public OldFDBigIntForTest( OldFDBigIntForTest other ){
- data = new int[nWords = other.nWords];
- System.arraycopy( other.data, 0, data, 0, nWords );
- }
-
- private OldFDBigIntForTest( int [] d, int n ){
- data = d;
- nWords = n;
- }
-
- public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){
- int n= (nd+8)/9; // estimate size needed.
- if ( n < 2 ) n = 2;
- data = new int[n]; // allocate enough space
- data[0] = (int)seed; // starting value
- data[1] = (int)(seed>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- int i = nd0;
- int limit = nd-5; // slurp digits 5 at a time.
- int v;
- while ( i < limit ){
- int ilim = i+5;
- v = (int)digit[i++]-(int)'0';
- while( i <ilim ){
- v = 10*v + (int)digit[i++]-(int)'0';
- }
- multaddMe( 100000, v); // ... where 100000 is 10^5.
- }
- int factor = 1;
- v = 0;
- while ( i < nd ){
- v = 10*v + (int)digit[i++]-(int)'0';
- factor *= 10;
- }
- if ( factor != 1 ){
- multaddMe( factor, v );
- }
- }
-
- /*
- * Left shift by c bits.
- * Shifts this in place.
- */
- public void
- lshiftMe( int c )throws IllegalArgumentException {
- if ( c <= 0 ){
- if ( c == 0 )
- return; // silly.
- else
- throw new IllegalArgumentException("negative shift count");
- }
- int wordcount = c>>5;
- int bitcount = c & 0x1f;
- int anticount = 32-bitcount;
- int t[] = data;
- int s[] = data;
- if ( nWords+wordcount+1 > t.length ){
- // reallocate.
- t = new int[ nWords+wordcount+1 ];
- }
- int target = nWords+wordcount;
- int src = nWords-1;
- if ( bitcount == 0 ){
- // special hack, since an anticount of 32 won't go!
- System.arraycopy( s, 0, t, wordcount, nWords );
- target = wordcount-1;
- } else {
- t[target--] = s[src]>>>anticount;
- while ( src >= 1 ){
- t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
- }
- t[target--] = s[src]<<bitcount;
- }
- while( target >= 0 ){
- t[target--] = 0;
- }
- data = t;
- nWords += wordcount + 1;
- // may have constructed high-order word of 0.
- // if so, trim it
- while ( nWords > 1 && data[nWords-1] == 0 )
- nWords--;
- }
-
- /*
- * normalize this number by shifting until
- * the MSB of the number is at 0x08000000.
- * This is in preparation for quoRemIteration, below.
- * The idea is that, to make division easier, we want the
- * divisor to be "normalized" -- usually this means shifting
- * the MSB into the high words sign bit. But because we know that
- * the quotient will be 0 < q < 10, we would like to arrange that
- * the dividend not span up into another word of precision.
- * (This needs to be explained more clearly!)
- */
- public int
- normalizeMe() throws IllegalArgumentException {
- int src;
- int wordcount = 0;
- int bitcount = 0;
- int v = 0;
- for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
- wordcount += 1;
- }
- if ( src < 0 ){
- // oops. Value is zero. Cannot normalize it!
- throw new IllegalArgumentException("zero value");
- }
- /*
- * In most cases, we assume that wordcount is zero. This only
- * makes sense, as we try not to maintain any high-order
- * words full of zeros. In fact, if there are zeros, we will
- * simply SHORTEN our number at this point. Watch closely...
- */
- nWords -= wordcount;
- /*
- * Compute how far left we have to shift v s.t. its highest-
- * order bit is in the right place. Then call lshiftMe to
- * do the work.
- */
- if ( (v & 0xf0000000) != 0 ){
- // will have to shift up into the next word.
- // too bad.
- for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
- v >>>= 1;
- } else {
- while ( v <= 0x000fffff ){
- // hack: byte-at-a-time shifting
- v <<= 8;
- bitcount += 8;
- }
- while ( v <= 0x07ffffff ){
- v <<= 1;
- bitcount += 1;
- }
- }
- if ( bitcount != 0 )
- lshiftMe( bitcount );
- return bitcount;
- }
-
- /*
- * Multiply a OldFDBigIntForTest by an int.
- * Result is a new OldFDBigIntForTest.
- */
- public OldFDBigIntForTest
- mult( int iv ) {
- long v = iv;
- int r[];
- long p;
-
- // guess adequate size of r.
- r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
- p = 0L;
- for( int i=0; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- r[i] = (int)p;
- p >>>= 32;
- }
- if ( p == 0L){
- return new OldFDBigIntForTest( r, nWords );
- } else {
- r[nWords] = (int)p;
- return new OldFDBigIntForTest( r, nWords+1 );
- }
- }
-
- /*
- * Multiply a OldFDBigIntForTest by an int and add another int.
- * Result is computed in place.
- * Hope it fits!
- */
- public void
- multaddMe( int iv, int addend ) {
- long v = iv;
- long p;
-
- // unroll 0th iteration, doing addition.
- p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
- data[0] = (int)p;
- p >>>= 32;
- for( int i=1; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>>= 32;
- }
- if ( p != 0L){
- data[nWords] = (int)p; // will fail noisily if illegal!
- nWords++;
- }
- }
-
- /*
- * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest.
- * Result is a new OldFDBigIntForTest.
- */
- public OldFDBigIntForTest
- mult( OldFDBigIntForTest other ){
- // crudely guess adequate size for r
- int r[] = new int[ nWords + other.nWords ];
- int i;
- // I think I am promised zeros...
-
- for( i = 0; i < this.nWords; i++ ){
- long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
- long p = 0L;
- int j;
- for( j = 0; j < other.nWords; j++ ){
- p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
- r[i+j] = (int)p;
- p >>>= 32;
- }
- r[i+j] = (int)p;
- }
- // compute how much of r we actually needed for all that.
- for ( i = r.length-1; i> 0; i--)
- if ( r[i] != 0 )
- break;
- return new OldFDBigIntForTest( r, i+1 );
- }
-
- /*
- * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest
- */
- public OldFDBigIntForTest
- add( OldFDBigIntForTest other ){
- int i;
- int a[], b[];
- int n, m;
- long c = 0L;
- // arrange such that a.nWords >= b.nWords;
- // n = a.nWords, m = b.nWords
- if ( this.nWords >= other.nWords ){
- a = this.data;
- n = this.nWords;
- b = other.data;
- m = other.nWords;
- } else {
- a = other.data;
- n = other.nWords;
- b = this.data;
- m = this.nWords;
- }
- int r[] = new int[ n ];
- for ( i = 0; i < n; i++ ){
- c += (long)a[i] & 0xffffffffL;
- if ( i < m ){
- c += (long)b[i] & 0xffffffffL;
- }
- r[i] = (int) c;
- c >>= 32; // signed shift.
- }
- if ( c != 0L ){
- // oops -- carry out -- need longer result.
- int s[] = new int[ r.length+1 ];
- System.arraycopy( r, 0, s, 0, r.length );
- s[i++] = (int)c;
- return new OldFDBigIntForTest( s, i );
- }
- return new OldFDBigIntForTest( r, i );
- }
-
- /*
- * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest
- * Assert that the result is positive.
- */
- public OldFDBigIntForTest
- sub( OldFDBigIntForTest other ){
- int r[] = new int[ this.nWords ];
- int i;
- int n = this.nWords;
- int m = other.nWords;
- int nzeros = 0;
- long c = 0L;
- for ( i = 0; i < n; i++ ){
- c += (long)this.data[i] & 0xffffffffL;
- if ( i < m ){
- c -= (long)other.data[i] & 0xffffffffL;
- }
- if ( ( r[i] = (int) c ) == 0 )
- nzeros++;
- else
- nzeros = 0;
- c >>= 32; // signed shift
- }
- assert c == 0L : c; // borrow out of subtract
- assert dataInRangeIsZero(i, m, other); // negative result of subtract
- return new OldFDBigIntForTest( r, n-nzeros );
- }
-
- private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) {
- while ( i < m )
- if (other.data[i++] != 0)
- return false;
- return true;
- }
-
- /*
- * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer
- * >0: this > other
- * 0: this == other
- * <0: this < other
- */
- public int
- cmp( OldFDBigIntForTest other ){
- int i;
- if ( this.nWords > other.nWords ){
- // if any of my high-order words is non-zero,
- // then the answer is evident
- int j = other.nWords-1;
- for ( i = this.nWords-1; i > j ; i-- )
- if ( this.data[i] != 0 ) return 1;
- }else if ( this.nWords < other.nWords ){
- // if any of other's high-order words is non-zero,
- // then the answer is evident
- int j = this.nWords-1;
- for ( i = other.nWords-1; i > j ; i-- )
- if ( other.data[i] != 0 ) return -1;
- } else{
- i = this.nWords-1;
- }
- for ( ; i > 0 ; i-- )
- if ( this.data[i] != other.data[i] )
- break;
- // careful! want unsigned compare!
- // use brute force here.
- int a = this.data[i];
- int b = other.data[i];
- if ( a < 0 ){
- // a is really big, unsigned
- if ( b < 0 ){
- return a-b; // both big, negative
- } else {
- return 1; // b not big, answer is obvious;
- }
- } else {
- // a is not really big
- if ( b < 0 ) {
- // but b is really big
- return -1;
- } else {
- return a - b;
- }
- }
- }
-
- /*
- * Compute
- * q = (int)( this / S )
- * this = 10 * ( this mod S )
- * Return q.
- * This is the iteration step of digit development for output.
- * We assume that S has been normalized, as above, and that
- * "this" has been lshift'ed accordingly.
- * Also assume, of course, that the result, q, can be expressed
- * as an integer, 0 <= q < 10.
- */
- public int
- quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException {
- // ensure that this and S have the same number of
- // digits. If S is properly normalized and q < 10 then
- // this must be so.
- if ( nWords != S.nWords ){
- throw new IllegalArgumentException("disparate values");
- }
- // estimate q the obvious way. We will usually be
- // right. If not, then we're only off by a little and
- // will re-add.
- int n = nWords-1;
- long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
- long diff = 0L;
- for ( int i = 0; i <= n ; i++ ){
- diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
- data[i] = (int)diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- if ( diff != 0L ) {
- // damn, damn, damn. q is too big.
- // add S back in until this turns +. This should
- // not be very many times!
- long sum = 0L;
- while ( sum == 0L ){
- sum = 0L;
- for ( int i = 0; i <= n; i++ ){
- sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
- data[i] = (int) sum;
- sum >>= 32; // Signed or unsigned, answer is 0 or 1
- }
- /*
- * Originally the following line read
- * "if ( sum !=0 && sum != -1 )"
- * but that would be wrong, because of the
- * treatment of the two values as entirely unsigned,
- * it would be impossible for a carry-out to be interpreted
- * as -1 -- it would have to be a single-bit carry-out, or
- * +1.
- */
- assert sum == 0 || sum == 1 : sum; // carry out of division correction
- q -= 1;
- }
- }
- // finally, we can multiply this by 10.
- // it cannot overflow, right, as the high-order word has
- // at least 4 high-order zeros!
- long p = 0L;
- for ( int i = 0; i <= n; i++ ){
- p += 10*((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>= 32; // SIGNED shift.
- }
- assert p == 0L : p; // Carry out of *10
- return (int)q;
- }
-
- public long
- longValue(){
- // if this can be represented as a long, return the value
- assert this.nWords > 0 : this.nWords; // longValue confused
-
- if (this.nWords == 1)
- return ((long)data[0]&0xffffffffL);
-
- assert dataInRangeIsZero(2, this.nWords, this); // value too big
- assert data[1] >= 0; // value too big
- return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
- }
-
- public String
- toString() {
- StringBuffer r = new StringBuffer(30);
- r.append('[');
- int i = Math.min( nWords-1, data.length-1) ;
- if ( nWords > data.length ){
- r.append( "("+data.length+"<"+nWords+"!)" );
- }
- for( ; i> 0 ; i-- ){
- r.append( Integer.toHexString( data[i] ) );
- r.append(' ');
- }
- r.append( Integer.toHexString( data[0] ) );
- r.append(']');
- return new String( r );
- }
-}
--- a/jdk/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2434 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-//package sun.misc;
-
-import java.util.regex.*;
-
-public class OldFloatingDecimalForTest{
- boolean isExceptional;
- boolean isNegative;
- int decExponent;
- char digits[];
- int nDigits;
- int bigIntExp;
- int bigIntNBits;
- boolean mustSetRoundDir = false;
- boolean fromHex = false;
- int roundDir = 0; // set by doubleValue
-
- /*
- * The fields below provides additional information about the result of
- * the binary to decimal digits conversion done in dtoa() and roundup()
- * methods. They are changed if needed by those two methods.
- */
-
- // True if the dtoa() binary to decimal conversion was exact.
- boolean exactDecimalConversion = false;
-
- // True if the result of the binary to decimal conversion was rounded-up
- // at the end of the conversion process, i.e. roundUp() method was called.
- boolean decimalDigitsRoundedUp = false;
-
- private OldFloatingDecimalForTest( boolean negSign, int decExponent, char []digits, int n, boolean e )
- {
- isNegative = negSign;
- isExceptional = e;
- this.decExponent = decExponent;
- this.digits = digits;
- this.nDigits = n;
- }
-
- /*
- * Constants of the implementation
- * Most are IEEE-754 related.
- * (There are more really boring constants at the end.)
- */
- static final long signMask = 0x8000000000000000L;
- static final long expMask = 0x7ff0000000000000L;
- static final long fractMask= ~(signMask|expMask);
- static final int expShift = 52;
- static final int expBias = 1023;
- static final long fractHOB = ( 1L<<expShift ); // assumed High-Order bit
- static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
- static final int maxSmallBinExp = 62;
- static final int minSmallBinExp = -( 63 / 3 );
- static final int maxDecimalDigits = 15;
- static final int maxDecimalExponent = 308;
- static final int minDecimalExponent = -324;
- static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
-
- static final long highbyte = 0xff00000000000000L;
- static final long highbit = 0x8000000000000000L;
- static final long lowbytes = ~highbyte;
-
- static final int singleSignMask = 0x80000000;
- static final int singleExpMask = 0x7f800000;
- static final int singleFractMask = ~(singleSignMask|singleExpMask);
- static final int singleExpShift = 23;
- static final int singleFractHOB = 1<<singleExpShift;
- static final int singleExpBias = 127;
- static final int singleMaxDecimalDigits = 7;
- static final int singleMaxDecimalExponent = 38;
- static final int singleMinDecimalExponent = -45;
-
- static final int intDecimalDigits = 9;
-
-
- /*
- * count number of bits from high-order 1 bit to low-order 1 bit,
- * inclusive.
- */
- private static int
- countBits( long v ){
- //
- // the strategy is to shift until we get a non-zero sign bit
- // then shift until we have no bits left, counting the difference.
- // we do byte shifting as a hack. Hope it helps.
- //
- if ( v == 0L ) return 0;
-
- while ( ( v & highbyte ) == 0L ){
- v <<= 8;
- }
- while ( v > 0L ) { // i.e. while ((v&highbit) == 0L )
- v <<= 1;
- }
-
- int n = 0;
- while (( v & lowbytes ) != 0L ){
- v <<= 8;
- n += 8;
- }
- while ( v != 0L ){
- v <<= 1;
- n += 1;
- }
- return n;
- }
-
- /*
- * Keep big powers of 5 handy for future reference.
- */
- private static OldFDBigIntForTest b5p[];
-
- private static synchronized OldFDBigIntForTest
- big5pow( int p ){
- assert p >= 0 : p; // negative power of 5
- if ( b5p == null ){
- b5p = new OldFDBigIntForTest[ p+1 ];
- }else if (b5p.length <= p ){
- OldFDBigIntForTest t[] = new OldFDBigIntForTest[ p+1 ];
- System.arraycopy( b5p, 0, t, 0, b5p.length );
- b5p = t;
- }
- if ( b5p[p] != null )
- return b5p[p];
- else if ( p < small5pow.length )
- return b5p[p] = new OldFDBigIntForTest( small5pow[p] );
- else if ( p < long5pow.length )
- return b5p[p] = new OldFDBigIntForTest( long5pow[p] );
- else {
- // construct the value.
- // recursively.
- int q, r;
- // in order to compute 5^p,
- // compute its square root, 5^(p/2) and square.
- // or, let q = p / 2, r = p -q, then
- // 5^p = 5^(q+r) = 5^q * 5^r
- q = p >> 1;
- r = p - q;
- OldFDBigIntForTest bigq = b5p[q];
- if ( bigq == null )
- bigq = big5pow ( q );
- if ( r < small5pow.length ){
- return (b5p[p] = bigq.mult( small5pow[r] ) );
- }else{
- OldFDBigIntForTest bigr = b5p[ r ];
- if ( bigr == null )
- bigr = big5pow( r );
- return (b5p[p] = bigq.mult( bigr ) );
- }
- }
- }
-
- //
- // a common operation
- //
- private static OldFDBigIntForTest
- multPow52( OldFDBigIntForTest v, int p5, int p2 ){
- if ( p5 != 0 ){
- if ( p5 < small5pow.length ){
- v = v.mult( small5pow[p5] );
- } else {
- v = v.mult( big5pow( p5 ) );
- }
- }
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- //
- // another common operation
- //
- private static OldFDBigIntForTest
- constructPow52( int p5, int p2 ){
- OldFDBigIntForTest v = new OldFDBigIntForTest( big5pow( p5 ) );
- if ( p2 != 0 ){
- v.lshiftMe( p2 );
- }
- return v;
- }
-
- /*
- * Make a floating double into a OldFDBigIntForTest.
- * This could also be structured as a OldFDBigIntForTest
- * constructor, but we'd have to build a lot of knowledge
- * about floating-point representation into it, and we don't want to.
- *
- * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- *
- */
- private OldFDBigIntForTest
- doubleToBigInt( double dval ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- lbits &= fractMask;
- if ( binexp > 0 ){
- lbits |= fractHOB;
- } else {
- assert lbits != 0L : lbits; // doubleToBigInt(0.0)
- binexp +=1;
- while ( (lbits & fractHOB ) == 0L){
- lbits <<= 1;
- binexp -= 1;
- }
- }
- binexp -= expBias;
- int nbits = countBits( lbits );
- /*
- * We now know where the high-order 1 bit is,
- * and we know how many there are.
- */
- int lowOrderZeros = expShift+1-nbits;
- lbits >>>= lowOrderZeros;
-
- bigIntExp = binexp+1-nbits;
- bigIntNBits = nbits;
- return new OldFDBigIntForTest( lbits );
- }
-
- /*
- * Compute a number that is the ULP of the given value,
- * for purposes of addition/subtraction. Generally easy.
- * More difficult if subtracting and the argument
- * is a normalized a power of 2, as the ULP changes at these points.
- */
- private static double ulp( double dval, boolean subtracting ){
- long lbits = Double.doubleToLongBits( dval ) & ~signMask;
- int binexp = (int)(lbits >>> expShift);
- double ulpval;
- if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
- // for subtraction from normalized, powers of 2,
- // use next-smaller exponent
- binexp -= 1;
- }
- if ( binexp > expShift ){
- ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))<<expShift );
- } else if ( binexp == 0 ){
- ulpval = Double.MIN_VALUE;
- } else {
- ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
- }
- if ( subtracting ) ulpval = - ulpval;
-
- return ulpval;
- }
-
- /*
- * Round a double to a float.
- * In addition to the fraction bits of the double,
- * look at the class instance variable roundDir,
- * which should help us avoid double-rounding error.
- * roundDir was set in hardValueOf if the estimate was
- * close enough, but not exact. It tells us which direction
- * of rounding is preferred.
- */
- float
- stickyRound( double dval ){
- long lbits = Double.doubleToLongBits( dval );
- long binexp = lbits & expMask;
- if ( binexp == 0L || binexp == expMask ){
- // what we have here is special.
- // don't worry, the right thing will happen.
- return (float) dval;
- }
- lbits += (long)roundDir; // hack-o-matic.
- return (float)Double.longBitsToDouble( lbits );
- }
-
-
- /*
- * This is the easy subcase --
- * all the significant bits, after scaling, are held in lvalue.
- * negSign and decExponent tell us what processing and scaling
- * has already been done. Exceptional cases have already been
- * stripped out.
- * In particular:
- * lvalue is a finite number (not Inf, nor NaN)
- * lvalue > 0L (not zero, nor negative).
- *
- * The only reason that we develop the digits here, rather than
- * calling on Long.toString() is that we can do it a little faster,
- * and besides want to treat trailing 0s specially. If Long.toString
- * changes, we should re-evaluate this strategy!
- */
- private void
- developLongDigits( int decExponent, long lvalue, long insignificant ){
- char digits[];
- int ndigits;
- int digitno;
- int c;
- //
- // Discard non-significant low-order bits, while rounding,
- // up to insignificant value.
- int i;
- for ( i = 0; insignificant >= 10L; i++ )
- insignificant /= 10L;
- if ( i != 0 ){
- long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
- long residue = lvalue % pow10;
- lvalue /= pow10;
- decExponent += i;
- if ( residue >= (pow10>>1) ){
- // round up based on the low-order bits we're discarding
- lvalue++;
- }
- }
- if ( lvalue <= Integer.MAX_VALUE ){
- assert lvalue > 0L : lvalue; // lvalue <= 0
- // even easier subcase!
- // can do int arithmetic rather than long!
- int ivalue = (int)lvalue;
- ndigits = 10;
- digits = perThreadBuffer.get();
- digitno = ndigits-1;
- c = ivalue%10;
- ivalue /= 10;
- while ( c == 0 ){
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- while ( ivalue != 0){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = ivalue%10;
- ivalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- } else {
- // same algorithm as above (same bugs, too )
- // but using long arithmetic.
- ndigits = 20;
- digits = perThreadBuffer.get();
- digitno = ndigits-1;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- while ( c == 0 ){
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10L;
- }
- while ( lvalue != 0L ){
- digits[digitno--] = (char)(c+'0');
- decExponent++;
- c = (int)(lvalue%10L);
- lvalue /= 10;
- }
- digits[digitno] = (char)(c+'0');
- }
- char result [];
- ndigits -= digitno;
- result = new char[ ndigits ];
- System.arraycopy( digits, digitno, result, 0, ndigits );
- this.digits = result;
- this.decExponent = decExponent+1;
- this.nDigits = ndigits;
- }
-
- //
- // add one to the least significant digit.
- // in the unlikely event there is a carry out,
- // deal with it.
- // assert that this will only happen where there
- // is only one digit, e.g. (float)1e-44 seems to do it.
- //
- private void
- roundup(){
- int i;
- int q = digits[ i = (nDigits-1)];
- if ( q == '9' ){
- while ( q == '9' && i > 0 ){
- digits[i] = '0';
- q = digits[--i];
- }
- if ( q == '9' ){
- // carryout! High-order 1, rest 0s, larger exp.
- decExponent += 1;
- digits[0] = '1';
- return;
- }
- // else fall through.
- }
- digits[i] = (char)(q+1);
- decimalDigitsRoundedUp = true;
- }
-
- public boolean digitsRoundedUp() {
- return decimalDigitsRoundedUp;
- }
-
- /*
- * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
- */
- public OldFloatingDecimalForTest( double d )
- {
- long dBits = Double.doubleToLongBits( d );
- long fractBits;
- int binExp;
- int nSignificantBits;
-
- // discover and delete sign
- if ( (dBits&signMask) != 0 ){
- isNegative = true;
- dBits ^= signMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (int)( (dBits&expMask) >> expShift );
- fractBits = dBits&fractMask;
- if ( binExp == (int)(expMask>>expShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0L ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&fractHOB) == 0L ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = expShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= fractHOB;
- nSignificantBits = expShift+1;
- }
- binExp -= expBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, fractBits, nSignificantBits );
- }
-
- /*
- * SECOND IMPORTANT CONSTRUCTOR: SINGLE
- */
- public OldFloatingDecimalForTest( float f )
- {
- int fBits = Float.floatToIntBits( f );
- int fractBits;
- int binExp;
- int nSignificantBits;
-
- // discover and delete sign
- if ( (fBits&singleSignMask) != 0 ){
- isNegative = true;
- fBits ^= singleSignMask;
- } else {
- isNegative = false;
- }
- // Begin to unpack
- // Discover obvious special cases of NaN and Infinity.
- binExp = (fBits&singleExpMask) >> singleExpShift;
- fractBits = fBits&singleFractMask;
- if ( binExp == (singleExpMask>>singleExpShift) ) {
- isExceptional = true;
- if ( fractBits == 0L ){
- digits = infinity;
- } else {
- digits = notANumber;
- isNegative = false; // NaN has no sign!
- }
- nDigits = digits.length;
- return;
- }
- isExceptional = false;
- // Finish unpacking
- // Normalize denormalized numbers.
- // Insert assumed high-order bit for normalized numbers.
- // Subtract exponent bias.
- if ( binExp == 0 ){
- if ( fractBits == 0 ){
- // not a denorm, just a 0!
- decExponent = 0;
- digits = zero;
- nDigits = 1;
- return;
- }
- while ( (fractBits&singleFractHOB) == 0 ){
- fractBits <<= 1;
- binExp -= 1;
- }
- nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count.
- binExp += 1;
- } else {
- fractBits |= singleFractHOB;
- nSignificantBits = singleExpShift+1;
- }
- binExp -= singleExpBias;
- // call the routine that actually does all the hard work.
- dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
- }
-
- private void
- dtoa( int binExp, long fractBits, int nSignificantBits )
- {
- int nFractBits; // number of significant bits of fractBits;
- int nTinyBits; // number of these to the right of the point.
- int decExp;
-
- // Examine number. Determine if it is an easy case,
- // which we can do pretty trivially using float/long conversion,
- // or whether we must do real work.
- nFractBits = countBits( fractBits );
- nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
- if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
- // Look more closely at the number to decide if,
- // with scaling by 10^nTinyBits, the result will fit in
- // a long.
- if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
- /*
- * We can do this:
- * take the fraction bits, which are normalized.
- * (a) nTinyBits == 0: Shift left or right appropriately
- * to align the binary point at the extreme right, i.e.
- * where a long int point is expected to be. The integer
- * result is easily converted to a string.
- * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
- * which effectively converts to long and scales by
- * 2^nTinyBits. Then multiply by 5^nTinyBits to
- * complete the scaling. We know this won't overflow
- * because we just counted the number of bits necessary
- * in the result. The integer you get from this can
- * then be converted to a string pretty easily.
- */
- long halfULP;
- if ( nTinyBits == 0 ) {
- if ( binExp > nSignificantBits ){
- halfULP = 1L << ( binExp-nSignificantBits-1);
- } else {
- halfULP = 0L;
- }
- if ( binExp >= expShift ){
- fractBits <<= (binExp-expShift);
- } else {
- fractBits >>>= (expShift-binExp) ;
- }
- developLongDigits( 0, fractBits, halfULP );
- return;
- }
- /*
- * The following causes excess digits to be printed
- * out in the single-float case. Our manipulation of
- * halfULP here is apparently not correct. If we
- * better understand how this works, perhaps we can
- * use this special case again. But for the time being,
- * we do not.
- * else {
- * fractBits >>>= expShift+1-nFractBits;
- * fractBits *= long5pow[ nTinyBits ];
- * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
- * developLongDigits( -nTinyBits, fractBits, halfULP );
- * return;
- * }
- */
- }
- }
- /*
- * This is the hard case. We are going to compute large positive
- * integers B and S and integer decExp, s.t.
- * d = ( B / S ) * 10^decExp
- * 1 <= B / S < 10
- * Obvious choices are:
- * decExp = floor( log10(d) )
- * B = d * 2^nTinyBits * 10^max( 0, -decExp )
- * S = 10^max( 0, decExp) * 2^nTinyBits
- * (noting that nTinyBits has already been forced to non-negative)
- * I am also going to compute a large positive integer
- * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
- * i.e. M is (1/2) of the ULP of d, scaled like B.
- * When we iterate through dividing B/S and picking off the
- * quotient bits, we will know when to stop when the remainder
- * is <= M.
- *
- * We keep track of powers of 2 and powers of 5.
- */
-
- /*
- * Estimate decimal exponent. (If it is small-ish,
- * we could double-check.)
- *
- * First, scale the mantissa bits such that 1 <= d2 < 2.
- * We are then going to estimate
- * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5)
- * and so we can estimate
- * log10(d) ~=~ log10(d2) + binExp * log10(2)
- * take the floor and call it decExp.
- * FIXME -- use more precise constants here. It costs no more.
- */
- double d2 = Double.longBitsToDouble(
- expOne | ( fractBits &~ fractHOB ) );
- decExp = (int)Math.floor(
- (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
- int B2, B5; // powers of 2 and powers of 5, respectively, in B
- int S2, S5; // powers of 2 and powers of 5, respectively, in S
- int M2, M5; // powers of 2 and powers of 5, respectively, in M
- int Bbits; // binary digits needed to represent B, approx.
- int tenSbits; // binary digits needed to represent 10*S, approx.
- OldFDBigIntForTest Sval, Bval, Mval;
-
- B5 = Math.max( 0, -decExp );
- B2 = B5 + nTinyBits + binExp;
-
- S5 = Math.max( 0, decExp );
- S2 = S5 + nTinyBits;
-
- M5 = B5;
- M2 = B2 - nSignificantBits;
-
- /*
- * the long integer fractBits contains the (nFractBits) interesting
- * bits from the mantissa of d ( hidden 1 added if necessary) followed
- * by (expShift+1-nFractBits) zeros. In the interest of compactness,
- * I will shift out those zeros before turning fractBits into a
- * OldFDBigIntForTest. The resulting whole number will be
- * d * 2^(nFractBits-1-binExp).
- */
- fractBits >>>= (expShift+1-nFractBits);
- B2 -= nFractBits-1;
- int common2factor = Math.min( B2, S2 );
- B2 -= common2factor;
- S2 -= common2factor;
- M2 -= common2factor;
-
- /*
- * HACK!! For exact powers of two, the next smallest number
- * is only half as far away as we think (because the meaning of
- * ULP changes at power-of-two bounds) for this reason, we
- * hack M2. Hope this works.
- */
- if ( nFractBits == 1 )
- M2 -= 1;
-
- if ( M2 < 0 ){
- // oops.
- // since we cannot scale M down far enough,
- // we must scale the other values up.
- B2 -= M2;
- S2 -= M2;
- M2 = 0;
- }
- /*
- * Construct, Scale, iterate.
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- char digits[] = this.digits = new char[18];
- int ndigit = 0;
- boolean low, high;
- long lowDigitDifference;
- int q;
-
- /*
- * Detect the special cases where all the numbers we are about
- * to compute will fit in int or long integers.
- * In these cases, we will avoid doing OldFDBigIntForTest arithmetic.
- * We use the same algorithms, except that we "normalize"
- * our OldFDBigIntForTests before iterating. This is to make division easier,
- * as it makes our fist guess (quotient of high-order words)
- * more accurate!
- *
- * Some day, we'll write a stopping test that takes
- * account of the asymmetry of the spacing of floating-point
- * numbers below perfect powers of 2
- * 26 Sept 96 is not that day.
- * So we use a symmetric test.
- */
- Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
- tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
- if ( Bbits < 64 && tenSbits < 64){
- if ( Bbits < 32 && tenSbits < 32){
- // wa-hoo! They're all ints!
- int b = ((int)fractBits * small5pow[B5] ) << B2;
- int s = small5pow[S5] << S2;
- int m = small5pow[M5] << M2;
- int tens = s * 10;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = b / s;
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- } else {
- // still good! they're all longs!
- long b = (fractBits * long5pow[B5] ) << B2;
- long s = long5pow[S5] << S2;
- long m = long5pow[M5] << M2;
- long tens = s * 10L;
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = (int) ( b / s );
- b = 10L * ( b % s );
- m *= 10L;
- low = (b < m );
- high = (b+m > tens );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = (int) ( b / s );
- b = 10 * ( b % s );
- m *= 10;
- assert q < 10 : q; // excessively large digit
- if ( m > 0L ){
- low = (b < m );
- high = (b+m > tens );
- } else {
- // hack -- m might overflow!
- // in this case, it is certainly > b,
- // which won't
- // and b+m > tens, too, since that has overflowed
- // either!
- low = true;
- high = true;
- }
- digits[ndigit++] = (char)('0' + q);
- }
- lowDigitDifference = (b<<1) - tens;
- exactDecimalConversion = (b == 0);
- }
- } else {
- OldFDBigIntForTest ZeroVal = new OldFDBigIntForTest(0);
- OldFDBigIntForTest tenSval;
- int shiftBias;
-
- /*
- * We really must do OldFDBigIntForTest arithmetic.
- * Fist, construct our OldFDBigIntForTest initial values.
- */
- Bval = multPow52( new OldFDBigIntForTest( fractBits ), B5, B2 );
- Sval = constructPow52( S5, S2 );
- Mval = constructPow52( M5, M2 );
-
-
- // normalize so that division works better
- Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
- Mval.lshiftMe( shiftBias );
- tenSval = Sval.mult( 10 );
- /*
- * Unroll the first iteration. If our decExp estimate
- * was too high, our first quotient will be zero. In this
- * case, we discard it and decrement decExp.
- */
- ndigit = 0;
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- assert q < 10 : q; // excessively large digit
- if ( (q == 0) && ! high ){
- // oops. Usually ignore leading zero.
- decExp--;
- } else {
- digits[ndigit++] = (char)('0' + q);
- }
- /*
- * HACK! Java spec sez that we always have at least
- * one digit after the . in either F- or E-form output.
- * Thus we will need more than one digit if we're using
- * E-form
- */
- if ( decExp < -3 || decExp >= 8 ){
- high = low = false;
- }
- while( ! low && ! high ){
- q = Bval.quoRemIteration( Sval );
- Mval = Mval.mult( 10 );
- assert q < 10 : q; // excessively large digit
- low = (Bval.cmp( Mval ) < 0);
- high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
- digits[ndigit++] = (char)('0' + q);
- }
- if ( high && low ){
- Bval.lshiftMe(1);
- lowDigitDifference = Bval.cmp(tenSval);
- } else {
- lowDigitDifference = 0L; // this here only for flow analysis!
- }
- exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0);
- }
- this.decExponent = decExp+1;
- this.digits = digits;
- this.nDigits = ndigit;
- /*
- * Last digit gets rounded based on stopping condition.
- */
- if ( high ){
- if ( low ){
- if ( lowDigitDifference == 0L ){
- // it's a tie!
- // choose based on which digits we like.
- if ( (digits[nDigits-1]&1) != 0 ) roundup();
- } else if ( lowDigitDifference > 0 ){
- roundup();
- }
- } else {
- roundup();
- }
- }
- }
-
- public boolean decimalDigitsExact() {
- return exactDecimalConversion;
- }
-
- public String
- toString(){
- // most brain-dead version
- StringBuffer result = new StringBuffer( nDigits+8 );
- if ( isNegative ){ result.append( '-' ); }
- if ( isExceptional ){
- result.append( digits, 0, nDigits );
- } else {
- result.append( "0.");
- result.append( digits, 0, nDigits );
- result.append('e');
- result.append( decExponent );
- }
- return new String(result);
- }
-
- public String toJavaFormatString() {
- char result[] = perThreadBuffer.get();
- int i = getChars(result);
- return new String(result, 0, i);
- }
-
- private int getChars(char[] result) {
- assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
- int i = 0;
- if (isNegative) { result[0] = '-'; i = 1; }
- if (isExceptional) {
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- if (decExponent > 0 && decExponent < 8) {
- // print digits.digits.
- int charLength = Math.min(nDigits, decExponent);
- System.arraycopy(digits, 0, result, i, charLength);
- i += charLength;
- if (charLength < decExponent) {
- charLength = decExponent-charLength;
- System.arraycopy(zero, 0, result, i, charLength);
- i += charLength;
- result[i++] = '.';
- result[i++] = '0';
- } else {
- result[i++] = '.';
- if (charLength < nDigits) {
- int t = nDigits - charLength;
- System.arraycopy(digits, charLength, result, i, t);
- i += t;
- } else {
- result[i++] = '0';
- }
- }
- } else if (decExponent <=0 && decExponent > -3) {
- result[i++] = '0';
- result[i++] = '.';
- if (decExponent != 0) {
- System.arraycopy(zero, 0, result, i, -decExponent);
- i -= decExponent;
- }
- System.arraycopy(digits, 0, result, i, nDigits);
- i += nDigits;
- } else {
- result[i++] = digits[0];
- result[i++] = '.';
- if (nDigits > 1) {
- System.arraycopy(digits, 1, result, i, nDigits-1);
- i += nDigits-1;
- } else {
- result[i++] = '0';
- }
- result[i++] = 'E';
- int e;
- if (decExponent <= 0) {
- result[i++] = '-';
- e = -decExponent+1;
- } else {
- e = decExponent-1;
- }
- // decExponent has 1, 2, or 3, digits
- if (e <= 9) {
- result[i++] = (char)(e+'0');
- } else if (e <= 99) {
- result[i++] = (char)(e/10 +'0');
- result[i++] = (char)(e%10 + '0');
- } else {
- result[i++] = (char)(e/100+'0');
- e %= 100;
- result[i++] = (char)(e/10+'0');
- result[i++] = (char)(e%10 + '0');
- }
- }
- }
- return i;
- }
-
- // Per-thread buffer for string/stringbuffer conversion
- private static ThreadLocal<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
- protected synchronized char[] initialValue() {
- return new char[26];
- }
- };
-
- public void appendTo(Appendable buf) {
- char result[] = perThreadBuffer.get();
- int i = getChars(result);
- if (buf instanceof StringBuilder)
- ((StringBuilder) buf).append(result, 0, i);
- else if (buf instanceof StringBuffer)
- ((StringBuffer) buf).append(result, 0, i);
- else
- assert false;
- }
-
- @SuppressWarnings("fallthrough")
- public static OldFloatingDecimalForTest
- readJavaFormatString( String in ) throws NumberFormatException {
- boolean isNegative = false;
- boolean signSeen = false;
- int decExp;
- char c;
-
- parseNumber:
- try{
- in = in.trim(); // don't fool around with white space.
- // throws NullPointerException if null
- int l = in.length();
- if ( l == 0 ) throw new NumberFormatException("empty String");
- int i = 0;
- switch ( c = in.charAt( i ) ){
- case '-':
- isNegative = true;
- //FALLTHROUGH
- case '+':
- i++;
- signSeen = true;
- }
-
- // Check for NaN and Infinity strings
- c = in.charAt(i);
- if(c == 'N' || c == 'I') { // possible NaN or infinity
- boolean potentialNaN = false;
- char targetChars[] = null; // char array of "NaN" or "Infinity"
-
- if(c == 'N') {
- targetChars = notANumber;
- potentialNaN = true;
- } else {
- targetChars = infinity;
- }
-
- // compare Input string to "NaN" or "Infinity"
- int j = 0;
- while(i < l && j < targetChars.length) {
- if(in.charAt(i) == targetChars[j]) {
- i++; j++;
- }
- else // something is amiss, throw exception
- break parseNumber;
- }
-
- // For the candidate string to be a NaN or infinity,
- // all characters in input string and target char[]
- // must be matched ==> j must equal targetChars.length
- // and i must equal l
- if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
- return (potentialNaN ? new OldFloatingDecimalForTest(Double.NaN) // NaN has no sign
- : new OldFloatingDecimalForTest(isNegative?
- Double.NEGATIVE_INFINITY:
- Double.POSITIVE_INFINITY)) ;
- }
- else { // something went wrong, throw exception
- break parseNumber;
- }
-
- } else if (c == '0') { // check for hexadecimal floating-point number
- if (l > i+1 ) {
- char ch = in.charAt(i+1);
- if (ch == 'x' || ch == 'X' ) // possible hex string
- return parseHexString(in);
- }
- } // look for and process decimal floating-point string
-
- char[] digits = new char[ l ];
- int nDigits= 0;
- boolean decSeen = false;
- int decPt = 0;
- int nLeadZero = 0;
- int nTrailZero= 0;
- digitLoop:
- while ( i < l ){
- switch ( c = in.charAt( i ) ){
- case '0':
- if ( nDigits > 0 ){
- nTrailZero += 1;
- } else {
- nLeadZero += 1;
- }
- break; // out of switch.
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- while ( nTrailZero > 0 ){
- digits[nDigits++] = '0';
- nTrailZero -= 1;
- }
- digits[nDigits++] = c;
- break; // out of switch.
- case '.':
- if ( decSeen ){
- // already saw one ., this is the 2nd.
- throw new NumberFormatException("multiple points");
- }
- decPt = i;
- if ( signSeen ){
- decPt -= 1;
- }
- decSeen = true;
- break; // out of switch.
- default:
- break digitLoop;
- }
- i++;
- }
- /*
- * At this point, we've scanned all the digits and decimal
- * point we're going to see. Trim off leading and trailing
- * zeros, which will just confuse us later, and adjust
- * our initial decimal exponent accordingly.
- * To review:
- * we have seen i total characters.
- * nLeadZero of them were zeros before any other digits.
- * nTrailZero of them were zeros after any other digits.
- * if ( decSeen ), then a . was seen after decPt characters
- * ( including leading zeros which have been discarded )
- * nDigits characters were neither lead nor trailing
- * zeros, nor point
- */
- /*
- * special hack: if we saw no non-zero digits, then the
- * answer is zero!
- * Unfortunately, we feel honor-bound to keep parsing!
- */
- if ( nDigits == 0 ){
- digits = zero;
- nDigits = 1;
- if ( nLeadZero == 0 ){
- // we saw NO DIGITS AT ALL,
- // not even a crummy 0!
- // this is not allowed.
- break parseNumber; // go throw exception
- }
-
- }
-
- /* Our initial exponent is decPt, adjusted by the number of
- * discarded zeros. Or, if there was no decPt,
- * then its just nDigits adjusted by discarded trailing zeros.
- */
- if ( decSeen ){
- decExp = decPt - nLeadZero;
- } else {
- decExp = nDigits+nTrailZero;
- }
-
- /*
- * Look for 'e' or 'E' and an optionally signed integer.
- */
- if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
- int expSign = 1;
- int expVal = 0;
- int reallyBig = Integer.MAX_VALUE / 10;
- boolean expOverflow = false;
- switch( in.charAt(++i) ){
- case '-':
- expSign = -1;
- //FALLTHROUGH
- case '+':
- i++;
- }
- int expAt = i;
- expLoop:
- while ( i < l ){
- if ( expVal >= reallyBig ){
- // the next character will cause integer
- // overflow.
- expOverflow = true;
- }
- switch ( c = in.charAt(i++) ){
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- expVal = expVal*10 + ( (int)c - (int)'0' );
- continue;
- default:
- i--; // back up.
- break expLoop; // stop parsing exponent.
- }
- }
- int expLimit = bigDecimalExponent+nDigits+nTrailZero;
- if ( expOverflow || ( expVal > expLimit ) ){
- //
- // The intent here is to end up with
- // infinity or zero, as appropriate.
- // The reason for yielding such a small decExponent,
- // rather than something intuitive such as
- // expSign*Integer.MAX_VALUE, is that this value
- // is subject to further manipulation in
- // doubleValue() and floatValue(), and I don't want
- // it to be able to cause overflow there!
- // (The only way we can get into trouble here is for
- // really outrageous nDigits+nTrailZero, such as 2 billion. )
- //
- decExp = expSign*expLimit;
- } else {
- // this should not overflow, since we tested
- // for expVal > (MAX+N), where N >= abs(decExp)
- decExp = decExp + expSign*expVal;
- }
-
- // if we saw something not a digit ( or end of string )
- // after the [Ee][+-], without seeing any digits at all
- // this is certainly an error. If we saw some digits,
- // but then some trailing garbage, that might be ok.
- // so we just fall through in that case.
- // HUMBUG
- if ( i == expAt )
- break parseNumber; // certainly bad
- }
- /*
- * We parsed everything we could.
- * If there are leftovers, then this is not good input!
- */
- if ( i < l &&
- ((i != l - 1) ||
- (in.charAt(i) != 'f' &&
- in.charAt(i) != 'F' &&
- in.charAt(i) != 'd' &&
- in.charAt(i) != 'D'))) {
- break parseNumber; // go throw exception
- }
-
- return new OldFloatingDecimalForTest( isNegative, decExp, digits, nDigits, false );
- } catch ( StringIndexOutOfBoundsException e ){ }
- throw new NumberFormatException("For input string: \"" + in + "\"");
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a double.
- *
- * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
- * ROUNDING DIRECTION in case the result is really destined
- * for a single-precision float.
- */
-
- public strictfp double doubleValue(){
- int kDigits = Math.min( nDigits, maxDecimalDigits+1 );
- long lValue;
- double dValue;
- double rValue, tValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Double.NaN;
- else
- return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
- }
- else {
- if (mustSetRoundDir) {
- roundDir = 0;
- }
- /*
- * convert the lead kDigits to a long integer.
- */
- // (special performance hack: start to do it using int)
- int iValue = (int)digits[0]-(int)'0';
- int iDigits = Math.min( kDigits, intDecimalDigits );
- for ( int i=1; i < iDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- lValue = (long)iValue;
- for ( int i=iDigits; i < kDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- dValue = (double)lValue;
- int exp = decExponent-kDigits;
- /*
- * lValue now contains a long integer with the value of
- * the first kDigits digits of the number.
- * dValue contains the (double) of the same.
- */
-
- if ( nDigits <= maxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here
- */
- if (exp == 0 || dValue == 0.0)
- return (isNegative)? -dValue : dValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= maxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- rValue = dValue * small10pow[exp];
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- int slop = maxDecimalDigits - kDigits;
- if ( exp <= maxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- dValue *= small10pow[slop];
- rValue = dValue * small10pow[exp-slop];
-
- if ( mustSetRoundDir ){
- tValue = rValue / small10pow[exp-slop];
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -maxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- rValue = dValue / small10pow[-exp];
- tValue = rValue * small10pow[-exp];
- if ( mustSetRoundDir ){
- roundDir = ( tValue == dValue ) ? 0
- :( tValue < dValue ) ? 1
- : -1;
- }
- return (isNegative)? -rValue : rValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- }
-
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by approximating the right answer by,
- * naively, scaling by powers of 10.
- */
- if ( exp > 0 ){
- if ( decExponent > maxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- if ( (exp&15) != 0 ){
- dValue *= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= big10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could overflow.
- */
- double t = dValue * big10pow[j];
- if ( Double.isInfinite( t ) ){
- /*
- * It did overflow.
- * Look more closely at the result.
- * If the exponent is just one too large,
- * then use the maximum finite as our estimate
- * value. Else call the result infinity
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two larger than
- * Double.MAX_VALUE ).
- */
- t = dValue / 2.0;
- t *= big10pow[j];
- if ( Double.isInfinite( t ) ){
- return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
- }
- t = Double.MAX_VALUE;
- }
- dValue = t;
- }
- } else if ( exp < 0 ){
- exp = -exp;
- if ( decExponent < minDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0 : 0.0;
- }
- if ( (exp&15) != 0 ){
- dValue /= small10pow[exp&15];
- }
- if ( (exp>>=4) != 0 ){
- int j;
- for( j = 0; exp > 1; j++, exp>>=1 ){
- if ( (exp&1)!=0)
- dValue *= tiny10pow[j];
- }
- /*
- * The reason for the weird exp > 1 condition
- * in the above loop was so that the last multiply
- * would get unrolled. We handle it here.
- * It could underflow.
- */
- double t = dValue * tiny10pow[j];
- if ( t == 0.0 ){
- /*
- * It did underflow.
- * Look more closely at the result.
- * If the exponent is just one too small,
- * then use the minimum finite as our estimate
- * value. Else call the result 0.0
- * and punt it.
- * ( I presume this could happen because
- * rounding forces the result here to be
- * an ULP or two less than
- * Double.MIN_VALUE ).
- */
- t = dValue * 2.0;
- t *= tiny10pow[j];
- if ( t == 0.0 ){
- return (isNegative)? -0.0 : 0.0;
- }
- t = Double.MIN_VALUE;
- }
- dValue = t;
- }
- }
-
- /*
- * dValue is now approximately the result.
- * The hard part is adjusting it, by comparison
- * with OldFDBigIntForTest arithmetic.
- * Formulate the EXACT big-number result as
- * bigD0 * 10^exp
- */
- OldFDBigIntForTest bigD0 = new OldFDBigIntForTest( lValue, digits, kDigits, nDigits );
- exp = decExponent - nDigits;
-
- correctionLoop:
- while(true){
- /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
- * bigIntExp and bigIntNBits
- */
- OldFDBigIntForTest bigB = doubleToBigInt( dValue );
-
- /*
- * Scale bigD, bigB appropriately for
- * big-integer operations.
- * Naively, we multiply by powers of ten
- * and powers of two. What we actually do
- * is keep track of the powers of 5 and
- * powers of 2 we would use, then factor out
- * common divisors before doing the work.
- */
- int B2, B5; // powers of 2, 5 in bigB
- int D2, D5; // powers of 2, 5 in bigD
- int Ulp2; // powers of 2 in halfUlp.
- if ( exp >= 0 ){
- B2 = B5 = 0;
- D2 = D5 = exp;
- } else {
- B2 = B5 = -exp;
- D2 = D5 = 0;
- }
- if ( bigIntExp >= 0 ){
- B2 += bigIntExp;
- } else {
- D2 -= bigIntExp;
- }
- Ulp2 = B2;
- // shift bigB and bigD left by a number s. t.
- // halfUlp is still an integer.
- int hulpbias;
- if ( bigIntExp+bigIntNBits <= -expBias+1 ){
- // This is going to be a denormalized number
- // (if not actually zero).
- // half an ULP is at 2^-(expBias+expShift+1)
- hulpbias = bigIntExp+ expBias + expShift;
- } else {
- hulpbias = expShift + 2 - bigIntNBits;
- }
- B2 += hulpbias;
- D2 += hulpbias;
- // if there are common factors of 2, we might just as well
- // factor them out, as they add nothing useful.
- int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
- B2 -= common2;
- D2 -= common2;
- Ulp2 -= common2;
- // do multiplications by powers of 5 and 2
- bigB = multPow52( bigB, B5, B2 );
- OldFDBigIntForTest bigD = multPow52( new OldFDBigIntForTest( bigD0 ), D5, D2 );
- //
- // to recap:
- // bigB is the scaled-big-int version of our floating-point
- // candidate.
- // bigD is the scaled-big-int version of the exact value
- // as we understand it.
- // halfUlp is 1/2 an ulp of bigB, except for special cases
- // of exact powers of 2
- //
- // the plan is to compare bigB with bigD, and if the difference
- // is less than halfUlp, then we're satisfied. Otherwise,
- // use the ratio of difference to halfUlp to calculate a fudge
- // factor to add to the floating value, then go 'round again.
- //
- OldFDBigIntForTest diff;
- int cmpResult;
- boolean overvalue;
- if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
- overvalue = true; // our candidate is too big.
- diff = bigB.sub( bigD );
- if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
- // candidate is a normalized exact power of 2 and
- // is too big. We will be subtracting.
- // For our purposes, ulp is the ulp of the
- // next smaller range.
- Ulp2 -= 1;
- if ( Ulp2 < 0 ){
- // rats. Cannot de-scale ulp this far.
- // must scale diff in other direction.
- Ulp2 = 0;
- diff.lshiftMe( 1 );
- }
- }
- } else if ( cmpResult < 0 ){
- overvalue = false; // our candidate is too small.
- diff = bigD.sub( bigB );
- } else {
- // the candidate is exactly right!
- // this happens with surprising frequency
- break correctionLoop;
- }
- OldFDBigIntForTest halfUlp = constructPow52( B5, Ulp2 );
- if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
- // difference is small.
- // this is close enough
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else if ( cmpResult == 0 ){
- // difference is exactly half an ULP
- // round to some other value maybe, then finish
- dValue += 0.5*ulp( dValue, overvalue );
- // should check for bigIntNBits == 1 here??
- if (mustSetRoundDir) {
- roundDir = overvalue ? -1 : 1;
- }
- break correctionLoop;
- } else {
- // difference is non-trivial.
- // could scale addend by ratio of difference to
- // halfUlp here, if we bothered to compute that difference.
- // Most of the time ( I hope ) it is about 1 anyway.
- dValue += ulp( dValue, overvalue );
- if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
- break correctionLoop; // oops. Fell off end of range.
- continue; // try again.
- }
-
- }
- return (isNegative)? -dValue : dValue;
- }
- }
-
- /*
- * Take a FloatingDecimal, which we presumably just scanned in,
- * and find out what its value is, as a float.
- * This is distinct from doubleValue() to avoid the extremely
- * unlikely case of a double rounding error, wherein the conversion
- * to double has one rounding error, and the conversion of that double
- * to a float has another rounding error, IN THE WRONG DIRECTION,
- * ( because of the preference to a zero low-order bit ).
- */
-
- public strictfp float floatValue(){
- int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
- int iValue;
- float fValue;
-
- // First, check for NaN and Infinity values
- if(digits == infinity || digits == notANumber) {
- if(digits == notANumber)
- return Float.NaN;
- else
- return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
- }
- else {
- /*
- * convert the lead kDigits to an integer.
- */
- iValue = (int)digits[0]-(int)'0';
- for ( int i=1; i < kDigits; i++ ){
- iValue = iValue*10 + (int)digits[i]-(int)'0';
- }
- fValue = (float)iValue;
- int exp = decExponent-kDigits;
- /*
- * iValue now contains an integer with the value of
- * the first kDigits digits of the number.
- * fValue contains the (float) of the same.
- */
-
- if ( nDigits <= singleMaxDecimalDigits ){
- /*
- * possibly an easy case.
- * We know that the digits can be represented
- * exactly. And if the exponent isn't too outrageous,
- * the whole thing can be done with one operation,
- * thus one rounding error.
- * Note that all our constructors trim all leading and
- * trailing zeros, so simple values (including zero)
- * will always end up here.
- */
- if (exp == 0 || fValue == 0.0f)
- return (isNegative)? -fValue : fValue; // small floating integer
- else if ( exp >= 0 ){
- if ( exp <= singleMaxSmallTen ){
- /*
- * Can get the answer with one operation,
- * thus one roundoff.
- */
- fValue *= singleSmall10pow[exp];
- return (isNegative)? -fValue : fValue;
- }
- int slop = singleMaxDecimalDigits - kDigits;
- if ( exp <= singleMaxSmallTen+slop ){
- /*
- * We can multiply dValue by 10^(slop)
- * and it is still "small" and exact.
- * Then we can multiply by 10^(exp-slop)
- * with one rounding.
- */
- fValue *= singleSmall10pow[slop];
- fValue *= singleSmall10pow[exp-slop];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a positive exp.
- */
- } else {
- if ( exp >= -singleMaxSmallTen ){
- /*
- * Can get the answer in one division.
- */
- fValue /= singleSmall10pow[-exp];
- return (isNegative)? -fValue : fValue;
- }
- /*
- * Else we have a hard case with a negative exp.
- */
- }
- } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
- /*
- * In double-precision, this is an exact floating integer.
- * So we can compute to double, then shorten to float
- * with one round, and get the right answer.
- *
- * First, finish accumulating digits.
- * Then convert that integer to a double, multiply
- * by the appropriate power of ten, and convert to float.
- */
- long lValue = (long)iValue;
- for ( int i=kDigits; i < nDigits; i++ ){
- lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
- }
- double dValue = (double)lValue;
- exp = decExponent-nDigits;
- dValue *= small10pow[exp];
- fValue = (float)dValue;
- return (isNegative)? -fValue : fValue;
-
- }
- /*
- * Harder cases:
- * The sum of digits plus exponent is greater than
- * what we think we can do with one error.
- *
- * Start by weeding out obviously out-of-range
- * results, then convert to double and go to
- * common hard-case code.
- */
- if ( decExponent > singleMaxDecimalExponent+1 ){
- /*
- * Lets face it. This is going to be
- * Infinity. Cut to the chase.
- */
- return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
- } else if ( decExponent < singleMinDecimalExponent-1 ){
- /*
- * Lets face it. This is going to be
- * zero. Cut to the chase.
- */
- return (isNegative)? -0.0f : 0.0f;
- }
-
- /*
- * Here, we do 'way too much work, but throwing away
- * our partial results, and going and doing the whole
- * thing as double, then throwing away half the bits that computes
- * when we convert back to float.
- *
- * The alternative is to reproduce the whole multiple-precision
- * algorithm for float precision, or to try to parameterize it
- * for common usage. The former will take about 400 lines of code,
- * and the latter I tried without success. Thus the semi-hack
- * answer here.
- */
- mustSetRoundDir = !fromHex;
- double dValue = doubleValue();
- return stickyRound( dValue );
- }
- }
-
-
- /*
- * All the positive powers of 10 that can be
- * represented exactly in double/float.
- */
- private static final double small10pow[] = {
- 1.0e0,
- 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
- 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
- 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
- 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
- 1.0e21, 1.0e22
- };
-
- private static final float singleSmall10pow[] = {
- 1.0e0f,
- 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
- 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
- };
-
- private static final double big10pow[] = {
- 1e16, 1e32, 1e64, 1e128, 1e256 };
- private static final double tiny10pow[] = {
- 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
- private static final int maxSmallTen = small10pow.length-1;
- private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
- private static final int small5pow[] = {
- 1,
- 5,
- 5*5,
- 5*5*5,
- 5*5*5*5,
- 5*5*5*5*5,
- 5*5*5*5*5*5,
- 5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5,
- 5*5*5*5*5*5*5*5*5*5*5*5*5
- };
-
-
- private static final long long5pow[] = {
- 1L,
- 5L,
- 5L*5,
- 5L*5*5,
- 5L*5*5*5,
- 5L*5*5*5*5,
- 5L*5*5*5*5*5,
- 5L*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
- };
-
- // approximately ceil( log2( long5pow[i] ) )
- private static final int n5bits[] = {
- 0,
- 3,
- 5,
- 7,
- 10,
- 12,
- 14,
- 17,
- 19,
- 21,
- 24,
- 26,
- 28,
- 31,
- 33,
- 35,
- 38,
- 40,
- 42,
- 45,
- 47,
- 49,
- 52,
- 54,
- 56,
- 59,
- 61,
- };
-
- private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
- private static final char notANumber[] = { 'N', 'a', 'N' };
- private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
-
-
- /*
- * Grammar is compatible with hexadecimal floating-point constants
- * described in section 6.4.4.2 of the C99 specification.
- */
- private static Pattern hexFloatPattern = null;
- private static synchronized Pattern getHexFloatPattern() {
- if (hexFloatPattern == null) {
- hexFloatPattern = Pattern.compile(
- //1 234 56 7 8 9
- "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
- );
- }
- return hexFloatPattern;
- }
-
- /*
- * Convert string s to a suitable floating decimal; uses the
- * double constructor and set the roundDir variable appropriately
- * in case the value is later converted to a float.
- */
- static OldFloatingDecimalForTest parseHexString(String s) {
- // Verify string is a member of the hexadecimal floating-point
- // string language.
- Matcher m = getHexFloatPattern().matcher(s);
- boolean validInput = m.matches();
-
- if (!validInput) {
- // Input does not match pattern
- throw new NumberFormatException("For input string: \"" + s + "\"");
- } else { // validInput
- /*
- * We must isolate the sign, significand, and exponent
- * fields. The sign value is straightforward. Since
- * floating-point numbers are stored with a normalized
- * representation, the significand and exponent are
- * interrelated.
- *
- * After extracting the sign, we normalized the
- * significand as a hexadecimal value, calculating an
- * exponent adjust for any shifts made during
- * normalization. If the significand is zero, the
- * exponent doesn't need to be examined since the output
- * will be zero.
- *
- * Next the exponent in the input string is extracted.
- * Afterwards, the significand is normalized as a *binary*
- * value and the input value's normalized exponent can be
- * computed. The significand bits are copied into a
- * double significand; if the string has more logical bits
- * than can fit in a double, the extra bits affect the
- * round and sticky bits which are used to round the final
- * value.
- */
-
- // Extract significand sign
- String group1 = m.group(1);
- double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
-
-
- // Extract Significand magnitude
- /*
- * Based on the form of the significand, calculate how the
- * binary exponent needs to be adjusted to create a
- * normalized *hexadecimal* floating-point number; that
- * is, a number where there is one nonzero hex digit to
- * the left of the (hexa)decimal point. Since we are
- * adjusting a binary, not hexadecimal exponent, the
- * exponent is adjusted by a multiple of 4.
- *
- * There are a number of significand scenarios to consider;
- * letters are used in indicate nonzero digits:
- *
- * 1. 000xxxx => x.xxx normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 2. 000xxx.yyyy => x.xxyyyy normalized
- * increase exponent by (number of x's - 1)*4
- *
- * 3. .000yyy => y.yy normalized
- * decrease exponent by (number of zeros + 1)*4
- *
- * 4. 000.00000yyy => y.yy normalized
- * decrease exponent by (number of zeros to right of point + 1)*4
- *
- * If the significand is exactly zero, return a properly
- * signed zero.
- */
-
- String significandString =null;
- int signifLength = 0;
- int exponentAdjust = 0;
- {
- int leftDigits = 0; // number of meaningful digits to
- // left of "decimal" point
- // (leading zeros stripped)
- int rightDigits = 0; // number of digits to right of
- // "decimal" point; leading zeros
- // must always be accounted for
- /*
- * The significand is made up of either
- *
- * 1. group 4 entirely (integer portion only)
- *
- * OR
- *
- * 2. the fractional portion from group 7 plus any
- * (optional) integer portions from group 6.
- */
- String group4;
- if( (group4 = m.group(4)) != null) { // Integer-only significand
- // Leading zeros never matter on the integer portion
- significandString = stripLeadingZeros(group4);
- leftDigits = significandString.length();
- }
- else {
- // Group 6 is the optional integer; leading zeros
- // never matter on the integer portion
- String group6 = stripLeadingZeros(m.group(6));
- leftDigits = group6.length();
-
- // fraction
- String group7 = m.group(7);
- rightDigits = group7.length();
-
- // Turn "integer.fraction" into "integer"+"fraction"
- significandString =
- ((group6 == null)?"":group6) + // is the null
- // check necessary?
- group7;
- }
-
- significandString = stripLeadingZeros(significandString);
- signifLength = significandString.length();
-
- /*
- * Adjust exponent as described above
- */
- if (leftDigits >= 1) { // Cases 1 and 2
- exponentAdjust = 4*(leftDigits - 1);
- } else { // Cases 3 and 4
- exponentAdjust = -4*( rightDigits - signifLength + 1);
- }
-
- // If the significand is zero, the exponent doesn't
- // matter; return a properly signed zero.
-
- if (signifLength == 0) { // Only zeros in input
- return new OldFloatingDecimalForTest(sign * 0.0);
- }
- }
-
- // Extract Exponent
- /*
- * Use an int to read in the exponent value; this should
- * provide more than sufficient range for non-contrived
- * inputs. If reading the exponent in as an int does
- * overflow, examine the sign of the exponent and
- * significand to determine what to do.
- */
- String group8 = m.group(8);
- boolean positiveExponent = ( group8 == null ) || group8.equals("+");
- long unsignedRawExponent;
- try {
- unsignedRawExponent = Integer.parseInt(m.group(9));
- }
- catch (NumberFormatException e) {
- // At this point, we know the exponent is
- // syntactically well-formed as a sequence of
- // digits. Therefore, if an NumberFormatException
- // is thrown, it must be due to overflowing int's
- // range. Also, at this point, we have already
- // checked for a zero significand. Thus the signs
- // of the exponent and significand determine the
- // final result:
- //
- // significand
- // + -
- // exponent + +infinity -infinity
- // - +0.0 -0.0
- return new OldFloatingDecimalForTest(sign * (positiveExponent ?
- Double.POSITIVE_INFINITY : 0.0));
- }
-
- long rawExponent =
- (positiveExponent ? 1L : -1L) * // exponent sign
- unsignedRawExponent; // exponent magnitude
-
- // Calculate partially adjusted exponent
- long exponent = rawExponent + exponentAdjust ;
-
- // Starting copying non-zero bits into proper position in
- // a long; copy explicit bit too; this will be masked
- // later for normal values.
-
- boolean round = false;
- boolean sticky = false;
- int bitsCopied=0;
- int nextShift=0;
- long significand=0L;
- // First iteration is different, since we only copy
- // from the leading significand bit; one more exponent
- // adjust will be needed...
-
- // IMPORTANT: make leadingDigit a long to avoid
- // surprising shift semantics!
- long leadingDigit = getHexDigit(significandString, 0);
-
- /*
- * Left shift the leading digit (53 - (bit position of
- * leading 1 in digit)); this sets the top bit of the
- * significand to 1. The nextShift value is adjusted
- * to take into account the number of bit positions of
- * the leadingDigit actually used. Finally, the
- * exponent is adjusted to normalize the significand
- * as a binary value, not just a hex value.
- */
- if (leadingDigit == 1) {
- significand |= leadingDigit << 52;
- nextShift = 52 - 4;
- /* exponent += 0 */ }
- else if (leadingDigit <= 3) { // [2, 3]
- significand |= leadingDigit << 51;
- nextShift = 52 - 5;
- exponent += 1;
- }
- else if (leadingDigit <= 7) { // [4, 7]
- significand |= leadingDigit << 50;
- nextShift = 52 - 6;
- exponent += 2;
- }
- else if (leadingDigit <= 15) { // [8, f]
- significand |= leadingDigit << 49;
- nextShift = 52 - 7;
- exponent += 3;
- } else {
- throw new AssertionError("Result from digit conversion too large!");
- }
- // The preceding if-else could be replaced by a single
- // code block based on the high-order bit set in
- // leadingDigit. Given leadingOnePosition,
-
- // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
- // nextShift = 52 - (3 + leadingOnePosition);
- // exponent += (leadingOnePosition-1);
-
-
- /*
- * Now the exponent variable is equal to the normalized
- * binary exponent. Code below will make representation
- * adjustments if the exponent is incremented after
- * rounding (includes overflows to infinity) or if the
- * result is subnormal.
- */
-
- // Copy digit into significand until the significand can't
- // hold another full hex digit or there are no more input
- // hex digits.
- int i = 0;
- for(i = 1;
- i < signifLength && nextShift >= 0;
- i++) {
- long currentDigit = getHexDigit(significandString, i);
- significand |= (currentDigit << nextShift);
- nextShift-=4;
- }
-
- // After the above loop, the bulk of the string is copied.
- // Now, we must copy any partial hex digits into the
- // significand AND compute the round bit and start computing
- // sticky bit.
-
- if ( i < signifLength ) { // at least one hex input digit exists
- long currentDigit = getHexDigit(significandString, i);
-
- // from nextShift, figure out how many bits need
- // to be copied, if any
- switch(nextShift) { // must be negative
- case -1:
- // three bits need to be copied in; can
- // set round bit
- significand |= ((currentDigit & 0xEL) >> 1);
- round = (currentDigit & 0x1L) != 0L;
- break;
-
- case -2:
- // two bits need to be copied in; can
- // set round and start sticky
- significand |= ((currentDigit & 0xCL) >> 2);
- round = (currentDigit &0x2L) != 0L;
- sticky = (currentDigit & 0x1L) != 0;
- break;
-
- case -3:
- // one bit needs to be copied in
- significand |= ((currentDigit & 0x8L)>>3);
- // Now set round and start sticky, if possible
- round = (currentDigit &0x4L) != 0L;
- sticky = (currentDigit & 0x3L) != 0;
- break;
-
- case -4:
- // all bits copied into significand; set
- // round and start sticky
- round = ((currentDigit & 0x8L) != 0); // is top bit set?
- // nonzeros in three low order bits?
- sticky = (currentDigit & 0x7L) != 0;
- break;
-
- default:
- throw new AssertionError("Unexpected shift distance remainder.");
- // break;
- }
-
- // Round is set; sticky might be set.
-
- // For the sticky bit, it suffices to check the
- // current digit and test for any nonzero digits in
- // the remaining unprocessed input.
- i++;
- while(i < signifLength && !sticky) {
- currentDigit = getHexDigit(significandString,i);
- sticky = sticky || (currentDigit != 0);
- i++;
- }
-
- }
- // else all of string was seen, round and sticky are
- // correct as false.
-
-
- // Check for overflow and update exponent accordingly.
-
- if (exponent > Double.MAX_EXPONENT) { // Infinite result
- // overflow to properly signed infinity
- return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY);
- } else { // Finite return value
- if (exponent <= Double.MAX_EXPONENT && // (Usually) normal result
- exponent >= Double.MIN_EXPONENT) {
-
- // The result returned in this block cannot be a
- // zero or subnormal; however after the
- // significand is adjusted from rounding, we could
- // still overflow in infinity.
-
- // AND exponent bits into significand; if the
- // significand is incremented and overflows from
- // rounding, this combination will update the
- // exponent correctly, even in the case of
- // Double.MAX_VALUE overflowing to infinity.
-
- significand = (( (exponent +
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
- } else { // Subnormal or zero
- // (exponent < Double.MIN_EXPONENT)
-
- if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
- // No way to round back to nonzero value
- // regardless of significand if the exponent is
- // less than -1075.
- return new OldFloatingDecimalForTest(sign * 0.0);
- } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023
- /*
- * Find bit position to round to; recompute
- * round and sticky bits, and shift
- * significand right appropriately.
- */
-
- sticky = sticky || round;
- round = false;
-
- // Number of bits of significand to preserve is
- // exponent - abs_min_exp +1
- // check:
- // -1075 +1074 + 1 = 0
- // -1023 +1074 + 1 = 52
-
- int bitsDiscarded = 53 -
- ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
- assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
- // What to do here:
- // First, isolate the new round bit
- round = (significand & (1L << (bitsDiscarded -1))) != 0L;
- if (bitsDiscarded > 1) {
- // create mask to update sticky bits; low
- // order bitsDiscarded bits should be 1
- long mask = ~((~0L) << (bitsDiscarded -1));
- sticky = sticky || ((significand & mask) != 0L ) ;
- }
-
- // Now, discard the bits
- significand = significand >> bitsDiscarded;
-
- significand = (( ((long)(Double.MIN_EXPONENT -1) + // subnorm exp.
- (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK) |
- (DoubleConsts.SIGNIF_BIT_MASK & significand);
- }
- }
-
- // The significand variable now contains the currently
- // appropriate exponent bits too.
-
- /*
- * Determine if significand should be incremented;
- * making this determination depends on the least
- * significant bit and the round and sticky bits.
- *
- * Round to nearest even rounding table, adapted from
- * table 4.7 in "Computer Arithmetic" by IsraelKoren.
- * The digit to the left of the "decimal" point is the
- * least significant bit, the digits to the right of
- * the point are the round and sticky bits
- *
- * Number Round(x)
- * x0.00 x0.
- * x0.01 x0.
- * x0.10 x0.
- * x0.11 x1. = x0. +1
- * x1.00 x1.
- * x1.01 x1.
- * x1.10 x1. + 1
- * x1.11 x1. + 1
- */
- boolean incremented = false;
- boolean leastZero = ((significand & 1L) == 0L);
- if( ( leastZero && round && sticky ) ||
- ((!leastZero) && round )) {
- incremented = true;
- significand++;
- }
-
- OldFloatingDecimalForTest fd = new OldFloatingDecimalForTest(Math.copySign(
- Double.longBitsToDouble(significand),
- sign));
-
- /*
- * Set roundingDir variable field of fd properly so
- * that the input string can be properly rounded to a
- * float value. There are two cases to consider:
- *
- * 1. rounding to double discards sticky bit
- * information that would change the result of a float
- * rounding (near halfway case between two floats)
- *
- * 2. rounding to double rounds up when rounding up
- * would not occur when rounding to float.
- *
- * For former case only needs to be considered when
- * the bits rounded away when casting to float are all
- * zero; otherwise, float round bit is properly set
- * and sticky will already be true.
- *
- * The lower exponent bound for the code below is the
- * minimum (normalized) subnormal exponent - 1 since a
- * value with that exponent can round up to the
- * minimum subnormal value and the sticky bit
- * information must be preserved (i.e. case 1).
- */
- if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
- (exponent <= Float.MAX_EXPONENT ) ){
- // Outside above exponent range, the float value
- // will be zero or infinity.
-
- /*
- * If the low-order 28 bits of a rounded double
- * significand are 0, the double could be a
- * half-way case for a rounding to float. If the
- * double value is a half-way case, the double
- * significand may have to be modified to round
- * the the right float value (see the stickyRound
- * method). If the rounding to double has lost
- * what would be float sticky bit information, the
- * double significand must be incremented. If the
- * double value's significand was itself
- * incremented, the float value may end up too
- * large so the increment should be undone.
- */
- if ((significand & 0xfffffffL) == 0x0L) {
- // For negative values, the sign of the
- // roundDir is the same as for positive values
- // since adding 1 increasing the significand's
- // magnitude and subtracting 1 decreases the
- // significand's magnitude. If neither round
- // nor sticky is true, the double value is
- // exact and no adjustment is required for a
- // proper float rounding.
- if( round || sticky) {
- if (leastZero) { // prerounding lsb is 0
- // If round and sticky were both true,
- // and the least significant
- // significand bit were 0, the rounded
- // significand would not have its
- // low-order bits be zero. Therefore,
- // we only need to adjust the
- // significand if round XOR sticky is
- // true.
- if (round ^ sticky) {
- fd.roundDir = 1;
- }
- }
- else { // prerounding lsb is 1
- // If the prerounding lsb is 1 and the
- // resulting significand has its
- // low-order bits zero, the significand
- // was incremented. Here, we undo the
- // increment, which will ensure the
- // right guard and sticky bits for the
- // float rounding.
- if (round)
- fd.roundDir = -1;
- }
- }
- }
- }
-
- fd.fromHex = true;
- return fd;
- }
- }
- }
-
- /**
- * Return <code>s</code> with any leading zeros removed.
- */
- static String stripLeadingZeros(String s) {
- return s.replaceFirst("^0+", "");
- }
-
- /**
- * Extract a hexadecimal digit from position <code>position</code>
- * of string <code>s</code>.
- */
- static int getHexDigit(String s, int position) {
- int value = Character.digit(s.charAt(position), 16);
- if (value <= -1 || value >= 16) {
- throw new AssertionError("Unexpected failure of digit conversion of " +
- s.charAt(position));
- }
- return value;
- }
-
-
-}
--- a/jdk/test/sun/misc/FloatingDecimal/TestFDBigInteger.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,435 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.math.BigInteger;
-import java.util.Random;
-import sun.misc.FDBigInteger;
-
-/**
- * @test
- * @bug 7032154
- * @summary unit testys of sun.misc.FDBigInteger
- * @modules java.base/sun.misc
- * @author Dmitry Nadezhin
- */
-public class TestFDBigInteger {
-
- private static final int MAX_P5 = 413;
- private static final int MAX_P2 = 65;
- private static final long LONG_SIGN_MASK = (1L << 63);
- private static final BigInteger FIVE = BigInteger.valueOf(5);
- private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
- private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0));
- private static final FDBigInteger IMMUTABLE_MILLION = genMillion1();
- private static final FDBigInteger IMMUTABLE_BILLION = genBillion1();
- private static final FDBigInteger IMMUTABLE_TEN18 = genTen18();
-
- static {
- IMMUTABLE_ZERO.makeImmutable();
- IMMUTABLE_MILLION.makeImmutable();
- IMMUTABLE_BILLION.makeImmutable();
- IMMUTABLE_TEN18.makeImmutable();
- }
-
- private static FDBigInteger mutable(String hex, int offset) {
- char[] chars = new BigInteger(hex, 16).toString().toCharArray();
- return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32);
- }
-
- private static FDBigInteger immutable(String hex, int offset) {
- FDBigInteger fd = mutable(hex, offset);
- fd.makeImmutable();
- return fd;
- }
-
- private static BigInteger biPow52(int p5, int p2) {
- return FIVE.pow(p5).shiftLeft(p2);
- }
-
- // data.length == 1, nWords == 1, offset == 0
- private static FDBigInteger genMillion1() {
- return FDBigInteger.valueOfPow52(6, 0).leftShift(6);
- }
-
- // data.length == 2, nWords == 1, offset == 0
- private static FDBigInteger genMillion2() {
- return FDBigInteger.valueOfMulPow52(1000000L, 0, 0);
- }
-
- // data.length == 1, nWords == 1, offset == 0
- private static FDBigInteger genBillion1() {
- return FDBigInteger.valueOfPow52(9, 0).leftShift(9);
- }
-
- // data.length == 2, nWords == 2, offset == 0
- private static FDBigInteger genTen18() {
- return FDBigInteger.valueOfPow52(18, 0).leftShift(18);
- }
-
- private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception {
- if (!expected.equals(actual.toBigInteger())) {
- throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16));
- }
- }
-
- private static void testValueOfPow52(int p5, int p2) throws Exception {
- check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2),
- "valueOfPow52(" + p5 + "," + p2 + ")");
- }
-
- private static void testValueOfPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- testValueOfPow52(p5, p2);
- }
- }
- }
-
- private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception {
- BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK);
- if (value < 0) {
- bi = bi.setBit(63);
- }
- check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2),
- "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")");
- }
-
- private static void testValueOfMulPow52(long value, int p5) throws Exception {
- testValueOfMulPow52(value, p5, 0);
- testValueOfMulPow52(value, p5, 1);
- testValueOfMulPow52(value, p5, 30);
- testValueOfMulPow52(value, p5, 31);
- testValueOfMulPow52(value, p5, 33);
- testValueOfMulPow52(value, p5, 63);
- }
-
- private static void testValueOfMulPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- testValueOfMulPow52(0xFFFFFFFFL, p5);
- testValueOfMulPow52(0x123456789AL, p5);
- testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5);
- testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5);
- }
- }
-
- private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.leftShift(shift);
- if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) {
- throw new Exception("leftShift doesn't reuse its argument");
- }
- if (isImmutable) {
- check(bt, t, "leftShift corrupts its argument");
- }
- check(bt.shiftLeft(shift), r, "leftShift returns wrong result");
- }
-
- private static void testLeftShift() throws Exception {
- testLeftShift(IMMUTABLE_ZERO, 0, true);
- testLeftShift(IMMUTABLE_ZERO, 10, true);
- testLeftShift(MUTABLE_ZERO, 0, false);
- testLeftShift(MUTABLE_ZERO, 10, false);
-
- testLeftShift(IMMUTABLE_MILLION, 0, true);
- testLeftShift(IMMUTABLE_MILLION, 1, true);
- testLeftShift(IMMUTABLE_MILLION, 12, true);
- testLeftShift(IMMUTABLE_MILLION, 13, true);
- testLeftShift(IMMUTABLE_MILLION, 32, true);
- testLeftShift(IMMUTABLE_MILLION, 33, true);
- testLeftShift(IMMUTABLE_MILLION, 44, true);
- testLeftShift(IMMUTABLE_MILLION, 45, true);
-
- testLeftShift(genMillion1(), 0, false);
- testLeftShift(genMillion1(), 1, false);
- testLeftShift(genMillion1(), 12, false);
- testLeftShift(genMillion1(), 13, false);
- testLeftShift(genMillion1(), 25, false);
- testLeftShift(genMillion1(), 26, false);
- testLeftShift(genMillion1(), 32, false);
- testLeftShift(genMillion1(), 33, false);
- testLeftShift(genMillion1(), 44, false);
- testLeftShift(genMillion1(), 45, false);
-
- testLeftShift(genMillion2(), 0, false);
- testLeftShift(genMillion2(), 1, false);
- testLeftShift(genMillion2(), 12, false);
- testLeftShift(genMillion2(), 13, false);
- testLeftShift(genMillion2(), 25, false);
- testLeftShift(genMillion2(), 26, false);
- testLeftShift(genMillion2(), 32, false);
- testLeftShift(genMillion2(), 33, false);
- testLeftShift(genMillion2(), 44, false);
- testLeftShift(genMillion2(), 45, false);
- }
-
- private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bs = s.toBigInteger();
- int q = t.quoRemIteration(s);
- BigInteger[] qr = bt.divideAndRemainder(bs);
- if (!BigInteger.valueOf(q).equals(qr[0])) {
- throw new Exception("quoRemIteration returns incorrect quo");
- }
- check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem");
- }
-
- private static void testQuoRemIteration() throws Exception {
- // IMMUTABLE_TEN18 == 0de0b6b3a7640000
- // q = 0
- testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18);
- // q = 1 -> q = 0
- testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18);
- // q = 1
- testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18);
- testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18);
- // q = 18
- testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18);
- }
-
- private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bo = o.toBigInteger();
- int cmp = t.cmp(o);
- int bcmp = bt.compareTo(bo);
- if (bcmp != cmp) {
- throw new Exception("cmp returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "cmp corrupts this");
- check(bo, o, "cmp corrupts other");
- if (o.cmp(t) != -cmp) {
- throw new Exception("asymmetrical cmp");
- }
- check(bt, t, "cmp corrupts this");
- check(bo, o, "cmp corrupts other");
- }
-
- private static void testCmp() throws Exception {
- testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0));
- testCmp(mutable("FFFFFFFF", 0), mutable("1", 1));
- testCmp(mutable("5", 0), mutable("6", 0));
- testCmp(mutable("5", 0), mutable("5", 0));
- testCmp(mutable("5000000001", 0), mutable("500000001", 0));
- testCmp(mutable("5000000001", 0), mutable("6", 1));
- testCmp(mutable("5000000001", 0), mutable("5", 1));
- testCmp(mutable("5000000000", 0), mutable("5", 1));
- }
-
- private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception {
- FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2);
- BigInteger bt = t.toBigInteger();
- BigInteger bo = biPow52(p5, p2);
- int cmp = t.cmp(o);
- int bcmp = bt.compareTo(bo);
- if (bcmp != cmp) {
- throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "cmpPow52 corrupts this");
- check(bo, o, "cmpPow5 corrupts other");
- }
-
- private static void testCmpPow52() throws Exception {
- testCmpPow52(mutable("00000002", 1), 0, 31);
- testCmpPow52(mutable("00000002", 1), 0, 32);
- testCmpPow52(mutable("00000002", 1), 0, 33);
- testCmpPow52(mutable("00000002", 1), 0, 34);
- testCmpPow52(mutable("00000002", 1), 0, 64);
- testCmpPow52(mutable("00000003", 1), 0, 32);
- testCmpPow52(mutable("00000003", 1), 0, 33);
- testCmpPow52(mutable("00000003", 1), 0, 34);
- }
-
- private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception {
- BigInteger bt = t.toBigInteger();
- BigInteger bx = x.toBigInteger();
- BigInteger by = y.toBigInteger();
- int cmp = t.addAndCmp(x, y);
- int bcmp = bt.compareTo(bx.add(by));
- if (bcmp != cmp) {
- throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp);
- }
- check(bt, t, "addAndCmp corrupts this");
- check(bx, x, "addAndCmp corrupts x");
- check(by, y, "addAndCmp corrupts y");
- }
-
- private static void testAddAndCmp() throws Exception {
- testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0));
- testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO);
- testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0));
- testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0));
- testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0));
-
- testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1));
- testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1));
-
- testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
- testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1));
-
- testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0));
- testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0));
- }
-
- private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.multBy10();
- if ((bt.signum() == 0 || !isImmutable) && r != t) {
- throw new Exception("multBy10 of doesn't reuse its argument");
- }
- if (isImmutable) {
- check(bt, t, "multBy10 corrupts its argument");
- }
- check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result");
- }
-
- private static void testMultBy10() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- testMultBy10(value, false);
- value.makeImmutable();
- testMultBy10(value, true);
- }
- }
- }
-
- private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception {
- BigInteger bt = t.toBigInteger();
- FDBigInteger r = t.multByPow52(p5, p2);
- if (bt.signum() == 0 && r != t) {
- throw new Exception("multByPow52 of doesn't reuse its argument");
- }
- check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result");
- }
-
- private static void testMultByPow52() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- testMultByPow52(value, p5, p2);
- }
- }
- }
-
- private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
- BigInteger biLeft = left.toBigInteger();
- BigInteger biRight = right.toBigInteger();
- FDBigInteger diff = left.leftInplaceSub(right);
- if (!isImmutable && diff != left) {
- throw new Exception("leftInplaceSub of doesn't reuse its argument");
- }
- if (isImmutable) {
- check(biLeft, left, "leftInplaceSub corrupts its left immutable argument");
- }
- check(biRight, right, "leftInplaceSub corrupts its right argument");
- check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result");
- }
-
- private static void testLeftInplaceSub() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
-// for (int p5r = 0; p5r <= p5; p5r += 10) {
-// for (int p2r = 0; p2r <= p2; p2r += 10) {
- for (int p5r = 0; p5r <= p5; p5r++) {
- for (int p2r = 0; p2r <= p2; p2r++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- testLeftInplaceSub(left, right, false);
- left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- left.makeImmutable();
- testLeftInplaceSub(left, right, true);
- }
- }
- }
- }
- }
-
- private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception {
- BigInteger biLeft = left.toBigInteger();
- BigInteger biRight = right.toBigInteger();
- FDBigInteger diff = left.rightInplaceSub(right);
- if (!isImmutable && diff != right) {
- throw new Exception("rightInplaceSub of doesn't reuse its argument");
- }
- check(biLeft, left, "leftInplaceSub corrupts its left argument");
- if (isImmutable) {
- check(biRight, right, "leftInplaceSub corrupts its right immutable argument");
- }
- try {
- check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result");
- } catch (Exception e) {
- System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight));
- throw e;
- }
- }
-
- private static void testRightInplaceSub() throws Exception {
- for (int p5 = 0; p5 <= MAX_P5; p5++) {
- for (int p2 = 0; p2 <= MAX_P2; p2++) {
-// for (int p5r = 0; p5r <= p5; p5r += 10) {
-// for (int p2r = 0; p2r <= p2; p2r += 10) {
- for (int p5r = 0; p5r <= p5; p5r++) {
- for (int p2r = 0; p2r <= p2; p2r++) {
- // This strange way of creating a value ensures that it is mutable.
- FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2);
- FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- testRightInplaceSub(left, right, false);
- right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r);
- right.makeImmutable();
- testRightInplaceSub(left, right, true);
- }
- }
- }
- }
- }
-
- public static void main(String[] args) throws Exception {
- testValueOfPow52();
- testValueOfMulPow52();
- testLeftShift();
- testQuoRemIteration();
- testCmp();
- testCmpPow52();
- testAddAndCmp();
- // Uncomment the following for more comprehensize but slow testing.
- // testLeftInplaceSub();
- // testMultBy10();
- // testMultByPow52();
- // testRightInplaceSub();
- }
-}
--- a/jdk/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Random;
-import sun.misc.FloatingDecimal;
-
-/*
-OldFloatingDecimalForTest
-
-public class OldFloatingDecimalForTest {
- public boolean digitsRoundedUp();
- public OldFloatingDecimalForTest(double);
- public OldFloatingDecimalForTest(float);
- public boolean decimalDigitsExact();
- public java.lang.String toString();
- public java.lang.String toJavaFormatString();
- public void appendTo(java.lang.Appendable);
- public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException;
- public strictfp double doubleValue();
- public strictfp float floatValue();
-}
-
-sun.misc.FloatingDecimal
-
-public class sun.misc.FloatingDecimal {
- public sun.misc.FloatingDecimal();
- public static java.lang.String toJavaFormatString(double);
- public static java.lang.String toJavaFormatString(float);
- public static void appendTo(double, java.lang.Appendable);
- public static void appendTo(float, java.lang.Appendable);
- public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException;
- public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException;
- public static sun.misc.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double);
-}
-*/
-
-/**
- * @test
- * @bug 7032154
- * @summary unit tests of sun.misc.FloatingDecimal
- * @modules java.base/sun.misc
- * @library ../../../java/lang/Math
- * @build DoubleConsts FloatConsts
- * @run main TestFloatingDecimal
- * @author Brian Burkhalter
- * @key randomness
- */
-public class TestFloatingDecimal {
- private static enum ResultType {
- RESULT_EXCEPTION,
- RESULT_PRINT
- }
-
- private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT;
- private static final int NUM_RANDOM_TESTS = 100000;
-
- private static final Random RANDOM = new Random();
-
- private static void result(String message) {
- switch (RESULT_TYPE) {
- case RESULT_EXCEPTION:
- throw new RuntimeException(message);
- case RESULT_PRINT:
- System.err.println(message);
- break;
- default:
- assert false;
- }
- }
-
- private static int check(String test, Object expected, Object actual) {
- int failures = 0;
- if(!actual.equals(expected)) {
- failures++;
- result("Test "+test+" expected "+expected+" but obtained "+actual);
- }
- return failures;
- }
-
- private static int testAppendToDouble() {
- System.out.println(" testAppendToDouble");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- StringBuilder sb = new StringBuilder();
- ofd.appendTo(sb);
- String oldString = sb.toString();
- sb = new StringBuilder();
- FloatingDecimal.appendTo(d[j], sb);
- String newString = sb.toString();
- failures += check("testAppendToDouble", oldString, newString);
- }
- }
-
- return failures;
- }
-
- private static int testAppendToFloat() {
- System.out.println(" testAppendToFloat");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextLong(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- StringBuilder sb = new StringBuilder();
- ofd.appendTo(sb);
- String oldString = sb.toString();
- sb = new StringBuilder();
- FloatingDecimal.appendTo(f[j], sb);
- String newString = sb.toString();
- failures += check("testAppendToFloat", oldString, newString);
- }
- }
-
- return failures;
- }
-
- private static int testAppendTo() {
- System.out.println("testAppendTo");
- int failures = 0;
-
- failures += testAppendToDouble();
- failures += testAppendToFloat();
-
- return failures;
- }
-
- private static int testParseDouble() {
- System.out.println(" testParseDouble");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- String javaFormatString = ofd.toJavaFormatString();
- ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
- double oldDouble = ofd.doubleValue();
- double newDouble = FloatingDecimal.parseDouble(javaFormatString);
- failures += check("testParseDouble", oldDouble, newDouble);
- }
- }
-
- return failures;
- }
-
- private static int testParseFloat() {
- System.out.println(" testParseFloat");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextInt(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- String javaFormatString = ofd.toJavaFormatString();
- ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString);
- float oldFloat = ofd.floatValue();
- float newFloat = FloatingDecimal.parseFloat(javaFormatString);
- failures += check("testParseFloat", oldFloat, newFloat);
- }
- }
-
- return failures;
- }
-
- private static int testParse() {
- System.out.println("testParse");
- int failures = 0;
-
- failures += testParseDouble();
- failures += testParseFloat();
-
- return failures;
- }
-
- private static int testToJavaFormatStringDoubleFixed() {
- System.out.println(" testToJavaFormatStringDoubleFixed");
- int failures = 0;
-
- double[] d = new double [] {
- -5.9522650387500933e18, // dtoa() fast path
- 0.872989018674569, // dtoa() fast iterative - long
- 1.1317400099603851e308 // dtoa() slow iterative
- };
-
- for(int i = 0; i < d.length; i++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]);
- failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i]));
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringDoubleRandom() {
- System.out.println(" testToJavaFormatStringDoubleRandom");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- double[] d = new double[] {
- RANDOM.nextLong(),
- RANDOM.nextGaussian(),
- RANDOM.nextDouble()*Double.MAX_VALUE
- };
- for(int j = 0; j < d.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]);
- failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j]));
- }
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringDouble() {
- System.out.println(" testToJavaFormatStringDouble");
- int failures = 0;
- failures += testToJavaFormatStringDoubleFixed();
- failures += testToJavaFormatStringDoubleRandom();
- return failures;
- }
-
- private static int testToJavaFormatStringFloatFixed() {
- System.out.println(" testToJavaFormatStringFloatFixed");
- int failures = 0;
-
- float[] f = new float[] {
- -9.8784166e8f, // dtoa() fast path
- 0.70443946f, // dtoa() fast iterative - int
- 1.8254228e37f // dtoa() slow iterative
- };
-
- for(int i = 0; i < f.length; i++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]);
- failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i]));
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringFloatRandom() {
- System.out.println(" testToJavaFormatStringFloatRandom");
- int failures = 0;
-
- for(int i = 0; i < NUM_RANDOM_TESTS; i++) {
- float[] f = new float[] {
- RANDOM.nextInt(),
- (float)RANDOM.nextGaussian(),
- RANDOM.nextFloat()*Float.MAX_VALUE
- };
- for(int j = 0; j < f.length; j++) {
- OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]);
- failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j]));
- }
- }
-
- return failures;
- }
-
- private static int testToJavaFormatStringFloat() {
- System.out.println(" testToJavaFormatStringFloat");
- int failures = 0;
-
- failures += testToJavaFormatStringFloatFixed();
- failures += testToJavaFormatStringFloatRandom();
-
- return failures;
- }
-
- private static int testToJavaFormatString() {
- System.out.println("testToJavaFormatString");
- int failures = 0;
-
- failures += testToJavaFormatStringDouble();
- failures += testToJavaFormatStringFloat();
-
- return failures;
- }
-
- public static void main(String[] args) {
- int failures = 0;
-
- failures += testAppendTo();
- failures += testParse();
- failures += testToJavaFormatString();
-
- if (failures != 0) {
- throw new RuntimeException("" + failures + " failures while testing FloatingDecimal");
- }
- }
-}
--- a/jdk/test/sun/security/krb5/auto/MSOID2.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/krb5/auto/MSOID2.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,6 +30,7 @@
*/
import sun.security.jgss.GSSUtil;
+import sun.security.util.HexDumpEncoder;
// The basic krb5 test skeleton you can copy from
public class MSOID2 {
@@ -69,7 +70,7 @@
nt[pos] = (byte)newLen;
}
t = nt;
- new sun.misc.HexDumpEncoder().encodeBuffer(t, System.out);
+ new HexDumpEncoder().encodeBuffer(t, System.out);
}
if (t != null || !s.x().isEstablished()) t = s.take(t);
if (c.x().isEstablished() && s.x().isEstablished()) break;
--- a/jdk/test/sun/security/mscapi/PublicKeyInterop.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,7 +29,7 @@
import java.util.*;
import javax.crypto.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
/*
* Confirm interoperability of RSA public keys between SunMSCAPI and SunJCE
--- a/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/mscapi/PublicKeyInterop.sh Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,7 @@
# @test
# @bug 6888925
+# @modules java.base/sun.security.util
# @requires os.family == "windows"
# @run shell PublicKeyInterop.sh
# @summary SunMSCAPI's Cipher can't use RSA public keys obtained from other
--- a/jdk/test/sun/security/pkcs/pkcs7/SignerOrder.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/pkcs/pkcs7/SignerOrder.java Wed Jan 06 14:54:24 2016 +0000
@@ -40,7 +40,7 @@
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Date;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
--- a/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/pkcs/pkcs8/PKCS8Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,7 +43,7 @@
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS8Key;
import sun.security.provider.DSAPrivateKey;
import sun.security.util.DerOutputStream;
--- a/jdk/test/sun/security/pkcs/pkcs9/UnknownAttribute.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/pkcs/pkcs9/UnknownAttribute.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,7 @@
import java.io.*;
import java.util.Arrays;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
import sun.security.pkcs.PKCS9Attribute;
import sun.security.util.DerValue;
import sun.security.util.ObjectIdentifier;
--- a/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/tools/jarsigner/concise_jarsigner.sh Wed Jan 06 14:54:24 2016 +0000
@@ -69,8 +69,8 @@
# First part: output format
# ==========================================================
-$KT -genkeypair -alias a1 -dname CN=a1 -validity 365
-$KT -genkeypair -alias a2 -dname CN=a2 -validity 365
+$KT -genkeypair -alias a1 -dname CN=a1 -validity 366
+$KT -genkeypair -alias a2 -dname CN=a2 -validity 366
# a.jar includes 8 unsigned, 2 signed by a1 and a2, 2 signed by a3
$JAR cvf a.jar A1.class A2.class
--- a/jdk/test/sun/security/x509/X500Name/NullX500Name.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/security/x509/X500Name/NullX500Name.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,7 @@
import java.util.Arrays;
import sun.security.util.DerOutputStream;
import sun.security.x509.*;
-import sun.misc.HexDumpEncoder;
+import sun.security.util.HexDumpEncoder;
public class NullX500Name {
--- a/jdk/test/sun/text/resources/LocaleData.cldr Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/text/resources/LocaleData.cldr Wed Jan 06 14:54:24 2016 +0000
@@ -72,10 +72,10 @@
FormatData/en_GB/TimePatterns/1=HH:mm:ss z
FormatData/en_GB/TimePatterns/2=HH:mm:ss
FormatData/en_GB/TimePatterns/3=HH:mm
-FormatData/en_GB/DatePatterns/0=EEEE, MMMM d, y
-FormatData/en_GB/DatePatterns/1=MMMM d, y
-FormatData/en_GB/DatePatterns/2=MMM d, y
-FormatData/en_GB/DatePatterns/3=M/d/yy
+FormatData/en_GB/DatePatterns/0=EEEE, d MMMM y
+FormatData/en_GB/DatePatterns/1=d MMMM y
+FormatData/en_GB/DatePatterns/2=d MMM y
+FormatData/en_GB/DatePatterns/3=dd/MM/y
FormatData/en_GB/DateTimePatterns/0={1} 'at' {0}
# bug #4070795
@@ -398,10 +398,10 @@
FormatData/es_AR/NumberPatterns/0=#,##0.###
# FormatData/es_AR/NumberPatterns/1=$#,##0.00;($#,##0.00) # Changed; see bug 4122840
FormatData/es_AR/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_AR/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_AR/TimePatterns/1=H:mm:ss z
-FormatData/es_AR/TimePatterns/2=H:mm:ss
-FormatData/es_AR/TimePatterns/3=H:mm
+FormatData/es_AR/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_AR/TimePatterns/1=h:mm:ss a z
+FormatData/es_AR/TimePatterns/2=h:mm:ss a
+FormatData/es_AR/TimePatterns/3=h:mm a
FormatData/es_AR/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_AR/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_AR/DatePatterns/2=d MMM y
@@ -414,10 +414,10 @@
# FormatData/es_BO/NumberPatterns/1=B$#,##0.00;(B$#,##0.00) # Changed; see bug 4122840
FormatData/es_BO/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_BO/BOB=Bs
-FormatData/es_BO/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_BO/TimePatterns/1=H:mm:ss z
-FormatData/es_BO/TimePatterns/2=H:mm:ss
-FormatData/es_BO/TimePatterns/3=H:mm
+FormatData/es_BO/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_BO/TimePatterns/1=h:mm:ss a z
+FormatData/es_BO/TimePatterns/2=h:mm:ss a
+FormatData/es_BO/TimePatterns/3=h:mm a
FormatData/es_BO/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_BO/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_BO/DatePatterns/2=d MMM y
@@ -444,10 +444,10 @@
FormatData/es_CO/NumberPatterns/2=#,##0\u00a0%
# changed currency symbol during 5102005 bugfix
CurrencyNames/es_CO/COP=$
-FormatData/es_CO/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_CO/TimePatterns/1=H:mm:ss z
-FormatData/es_CO/TimePatterns/2=H:mm:ss
-FormatData/es_CO/TimePatterns/3=H:mm
+FormatData/es_CO/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_CO/TimePatterns/1=h:mm:ss a z
+FormatData/es_CO/TimePatterns/2=h:mm:ss a
+FormatData/es_CO/TimePatterns/3=h:mm a
FormatData/es_CO/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_CO/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_CO/DatePatterns/2=d/MM/y
@@ -461,10 +461,10 @@
# FormatData/es_CR/NumberPatterns/1=C#,##0.00;(C#,##0.00) # Changed; see bug 4122840
FormatData/es_CR/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_CR/CRC=\u20a1
-FormatData/es_CR/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_CR/TimePatterns/1=H:mm:ss z
-FormatData/es_CR/TimePatterns/2=H:mm:ss
-FormatData/es_CR/TimePatterns/3=H:mm
+FormatData/es_CR/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_CR/TimePatterns/1=h:mm:ss a z
+FormatData/es_CR/TimePatterns/2=h:mm:ss a
+FormatData/es_CR/TimePatterns/3=h:mm a
FormatData/es_CR/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_CR/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_CR/DatePatterns/2=d MMM y
@@ -477,10 +477,10 @@
# FormatData/es_DO/NumberPatterns/1=RD$#,##0.00;(RD$#,##0.00) # Changed; see bug 4122840
FormatData/es_DO/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_DO/DOP=$
-FormatData/es_DO/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_DO/TimePatterns/1=H:mm:ss z
-FormatData/es_DO/TimePatterns/2=H:mm:ss
-FormatData/es_DO/TimePatterns/3=H:mm
+FormatData/es_DO/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_DO/TimePatterns/1=h:mm:ss a z
+FormatData/es_DO/TimePatterns/2=h:mm:ss a
+FormatData/es_DO/TimePatterns/3=h:mm a
FormatData/es_DO/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_DO/DatePatterns/1=d 'de' MMMM 'de' y
# FormatData/es_DO/DatePatterns/2=MM/dd/yyyy # Changed: see bug 8037343
@@ -526,10 +526,10 @@
# FormatData/es_GT/NumberPatterns/1=Q#,##0.00;(Q#,##0.00) # Changed; see bug 4122840
FormatData/es_GT/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_GT/GTQ=Q
-FormatData/es_GT/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_GT/TimePatterns/1=H:mm:ss z
-FormatData/es_GT/TimePatterns/2=H:mm:ss
-FormatData/es_GT/TimePatterns/3=H:mm
+FormatData/es_GT/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_GT/TimePatterns/1=h:mm:ss a z
+FormatData/es_GT/TimePatterns/2=h:mm:ss a
+FormatData/es_GT/TimePatterns/3=h:mm a
FormatData/es_GT/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_GT/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_GT/DatePatterns/2=d/MM/y
@@ -542,10 +542,10 @@
# FormatData/es_HN/NumberPatterns/1=L#,##0.00;(L#,##0.00) # Changed; see bug 4122840
FormatData/es_HN/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_HN/HNL=L
-FormatData/es_HN/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_HN/TimePatterns/1=H:mm:ss z
-FormatData/es_HN/TimePatterns/2=H:mm:ss
-FormatData/es_HN/TimePatterns/3=H:mm
+FormatData/es_HN/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_HN/TimePatterns/1=h:mm:ss a z
+FormatData/es_HN/TimePatterns/2=h:mm:ss a
+FormatData/es_HN/TimePatterns/3=h:mm a
FormatData/es_HN/DatePatterns/0=EEEE dd 'de' MMMM 'de' y
FormatData/es_HN/DatePatterns/1=dd 'de' MMMM 'de' y
FormatData/es_HN/DatePatterns/2=d MMM y
@@ -558,10 +558,10 @@
# FormatData/es_MX/NumberPatterns/1=$#,##0.00;($#,##0.00) # Changed; see bug 4122840
FormatData/es_MX/NumberPatterns/2=#,##0%
CurrencyNames/es_MX/MXN=$
-FormatData/es_MX/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_MX/TimePatterns/1=H:mm:ss z
-FormatData/es_MX/TimePatterns/2=H:mm:ss
-FormatData/es_MX/TimePatterns/3=H:mm
+FormatData/es_MX/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_MX/TimePatterns/1=h:mm:ss a z
+FormatData/es_MX/TimePatterns/2=h:mm:ss a
+FormatData/es_MX/TimePatterns/3=h:mm a
FormatData/es_MX/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_MX/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_MX/DatePatterns/2=dd/MM/y
@@ -574,10 +574,10 @@
# FormatData/es_NI/NumberPatterns/1=$C#,##0.00;($C#,##0.00) # Changed; see bug 4122840
FormatData/es_NI/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_NI/NIO=C$
-FormatData/es_NI/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_NI/TimePatterns/1=H:mm:ss z
-FormatData/es_NI/TimePatterns/2=H:mm:ss
-FormatData/es_NI/TimePatterns/3=H:mm
+FormatData/es_NI/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_NI/TimePatterns/1=h:mm:ss a z
+FormatData/es_NI/TimePatterns/2=h:mm:ss a
+FormatData/es_NI/TimePatterns/3=h:mm a
FormatData/es_NI/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_NI/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_NI/DatePatterns/2=d MMM y
@@ -590,10 +590,10 @@
# FormatData/es_PA/NumberPatterns/1=B#,##0.00;(B#,##0.00) # Changed; see bug 4122840
FormatData/es_PA/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_PA/PAB=B/.
-FormatData/es_PA/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_PA/TimePatterns/1=H:mm:ss z
-FormatData/es_PA/TimePatterns/2=H:mm:ss
-FormatData/es_PA/TimePatterns/3=H:mm
+FormatData/es_PA/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_PA/TimePatterns/1=h:mm:ss a z
+FormatData/es_PA/TimePatterns/2=h:mm:ss a
+FormatData/es_PA/TimePatterns/3=h:mm a
FormatData/es_PA/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_PA/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_PA/DatePatterns/2=MM/dd/y
@@ -605,10 +605,10 @@
FormatData/es_PE/NumberPatterns/0=#,##0.###
# FormatData/es_PE/NumberPatterns/1=S/#,##0.00;S/-#,##0.00 # Changed; see bug 4122840
FormatData/es_PE/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_PE/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_PE/TimePatterns/1=H:mm:ss z
-FormatData/es_PE/TimePatterns/2=H:mm:ss
-FormatData/es_PE/TimePatterns/3=H:mm
+FormatData/es_PE/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_PE/TimePatterns/1=h:mm:ss a z
+FormatData/es_PE/TimePatterns/2=h:mm:ss a
+FormatData/es_PE/TimePatterns/3=h:mm a
FormatData/es_PE/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_PE/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_PE/DatePatterns/2=d MMM y
@@ -621,10 +621,10 @@
# FormatData/es_PR/NumberPatterns/1=$#,##0.00;($#,##0.00) # Changed; see bug 4122840
FormatData/es_PR/NumberPatterns/2=#,##0\u00a0%
CurrencyNames/es_PR/USD=$
-FormatData/es_PR/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_PR/TimePatterns/1=H:mm:ss z
-FormatData/es_PR/TimePatterns/2=H:mm:ss
-FormatData/es_PR/TimePatterns/3=H:mm
+FormatData/es_PR/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_PR/TimePatterns/1=h:mm:ss a z
+FormatData/es_PR/TimePatterns/2=h:mm:ss a
+FormatData/es_PR/TimePatterns/3=h:mm a
FormatData/es_PR/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_PR/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_PR/DatePatterns/2=MM/dd/y
@@ -637,10 +637,10 @@
FormatData/es_PY/NumberPatterns/0=#,##0.###
# FormatData/es_PY/NumberPatterns/1=G#,##0.00;(G#,##0.00) # Changed; see bug 4122840
FormatData/es_PY/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_PY/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_PY/TimePatterns/1=H:mm:ss z
-FormatData/es_PY/TimePatterns/2=H:mm:ss
-FormatData/es_PY/TimePatterns/3=H:mm
+FormatData/es_PY/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_PY/TimePatterns/1=h:mm:ss a z
+FormatData/es_PY/TimePatterns/2=h:mm:ss a
+FormatData/es_PY/TimePatterns/3=h:mm a
FormatData/es_PY/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_PY/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_PY/DatePatterns/2=d MMM y
@@ -653,10 +653,10 @@
# FormatData/es_SV/NumberPatterns/1=C#,##0.00;(C#,##0.00) # Changed; see bug 4122840
FormatData/es_SV/NumberPatterns/2=#,##0\u00a0%
#CurrencyNames/es_SV/SVC=<MISSING!>
-FormatData/es_SV/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_SV/TimePatterns/1=H:mm:ss z
-FormatData/es_SV/TimePatterns/2=H:mm:ss
-FormatData/es_SV/TimePatterns/3=H:mm
+FormatData/es_SV/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_SV/TimePatterns/1=h:mm:ss a z
+FormatData/es_SV/TimePatterns/2=h:mm:ss a
+FormatData/es_SV/TimePatterns/3=h:mm a
FormatData/es_SV/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_SV/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_SV/DatePatterns/2=d MMM y
@@ -669,10 +669,10 @@
FormatData/es_UY/NumberPatterns/0=#,##0.###
# FormatData/es_UY/NumberPatterns/1=NU$ #,##0.00;(NU$#,##0.00) # Changed; see bug 4122840
FormatData/es_UY/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_UY/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_UY/TimePatterns/1=H:mm:ss z
-FormatData/es_UY/TimePatterns/2=H:mm:ss
-FormatData/es_UY/TimePatterns/3=H:mm
+FormatData/es_UY/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_UY/TimePatterns/1=h:mm:ss a z
+FormatData/es_UY/TimePatterns/2=h:mm:ss a
+FormatData/es_UY/TimePatterns/3=h:mm a
FormatData/es_UY/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_UY/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_UY/DatePatterns/2=d MMM y
@@ -686,10 +686,10 @@
FormatData/es_VE/NumberPatterns/0=#,##0.###
# FormatData/es_VE/NumberPatterns/1=Bs#,##0.00;Bs -#,##0.00 # Changed; see bug 4122840
FormatData/es_VE/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_VE/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_VE/TimePatterns/1=H:mm:ss z
-FormatData/es_VE/TimePatterns/2=H:mm:ss
-FormatData/es_VE/TimePatterns/3=H:mm
+FormatData/es_VE/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_VE/TimePatterns/1=h:mm:ss a z
+FormatData/es_VE/TimePatterns/2=h:mm:ss a
+FormatData/es_VE/TimePatterns/3=h:mm a
FormatData/es_VE/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_VE/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_VE/DatePatterns/2=d MMM y
@@ -2372,22 +2372,22 @@
FormatData/en_AU/NumberPatterns/1=\u00a4#,##0.00
FormatData/en_NZ/NumberPatterns/1=\u00a4#,##0.00
FormatData/en_ZA/NumberPatterns/1=\u00a4#,##0.00
-FormatData/es_AR/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_BO/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_AR/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_BO/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_CL/NumberPatterns/1=\u00a4#,##0.00;\u00a4-#,##0.00
-FormatData/es_CO/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_CR/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_DO/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_CO/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_CR/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_DO/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_EC/NumberPatterns/1=\u00a4#,##0.00;\u00a4-#,##0.00
-FormatData/es_GT/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_HN/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_GT/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_HN/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_MX/NumberPatterns/1=\u00a4#,##0.00
-FormatData/es_NI/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_PA/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_PE/NumberPatterns/1=#,##0.00\u00a0\u00a4
-FormatData/es_PR/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_NI/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_PA/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_PE/NumberPatterns/1=\u00a4#,##0.00
+FormatData/es_PR/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_PY/NumberPatterns/1=\u00a4\u00a0#,##0.00;\u00a4\u00a0-#,##0.00
-FormatData/es_SV/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_SV/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_UY/NumberPatterns/1=\u00a4\u00a0#,##0.00
FormatData/es_VE/NumberPatterns/1=\u00a4#,##0.00;\u00a4-#,##0.00
FormatData/fr_FR/NumberPatterns/1=#,##0.00\u00a0\u00a4
@@ -2908,10 +2908,10 @@
FormatData/en_PH/TimePatterns/1=h:mm:ss a z
FormatData/en_PH/TimePatterns/2=h:mm:ss a
FormatData/en_PH/TimePatterns/3=h:mm a
-FormatData/en_PH/DatePatterns/0=EEEE, MMMM d, y
-FormatData/en_PH/DatePatterns/1=MMMM d, y
-FormatData/en_PH/DatePatterns/2=MMM d, y
-FormatData/en_PH/DatePatterns/3=M/d/yy
+FormatData/en_PH/DatePatterns/0=EEEE, d MMMM y
+FormatData/en_PH/DatePatterns/1=d MMMM y
+FormatData/en_PH/DatePatterns/2=d MMM y
+FormatData/en_PH/DatePatterns/3=dd/MM/y
FormatData/en_PH/DateTimePatterns/0={1} 'at' {0}
LocaleNames/en_PH/kj=Kuanyama
LocaleNames/en_PH/kl=Kalaallisut
@@ -3415,12 +3415,12 @@
FormatData/es_US/Eras/0=a. C.
FormatData/es_US/Eras/1=d. C.
FormatData/es_US/NumberPatterns/0=#,##0.###
-FormatData/es_US/NumberPatterns/1=#,##0.00\u00a0\u00a4
+FormatData/es_US/NumberPatterns/1=\u00a4#,##0.00
FormatData/es_US/NumberPatterns/2=#,##0\u00a0%
-FormatData/es_US/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_US/TimePatterns/1=H:mm:ss z
-FormatData/es_US/TimePatterns/2=H:mm:ss
-FormatData/es_US/TimePatterns/3=H:mm
+FormatData/es_US/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_US/TimePatterns/1=h:mm:ss a z
+FormatData/es_US/TimePatterns/2=h:mm:ss a
+FormatData/es_US/TimePatterns/3=h:mm a
FormatData/es_US/DatePatterns/0=EEEE, d 'de' MMMM 'de' y
FormatData/es_US/DatePatterns/1=d 'de' MMMM 'de' y
FormatData/es_US/DatePatterns/2=d MMM y
@@ -5605,7 +5605,7 @@
#CalendarData/sl/firstDayOfWeek=<MISSING!>
# bug 6573250
-CurrencyNames/en_CA/USD=$
+CurrencyNames/en_CA/USD=US$
# bug 6870908
FormatData/et/MonthNames/0=jaanuar
@@ -7684,14 +7684,14 @@
FormatData/sv_SE/NumberPatterns/2=#,##0\u00a0%
# bug 8017142
-FormatData/es_CL/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_CL/TimePatterns/1=H:mm:ss z
-FormatData/es_CL/TimePatterns/2=H:mm:ss
-FormatData/es_CL/TimePatterns/3=H:mm
-FormatData/es_EC/TimePatterns/0=H:mm:ss (zzzz)
-FormatData/es_EC/TimePatterns/1=H:mm:ss z
-FormatData/es_EC/TimePatterns/2=H:mm:ss
-FormatData/es_EC/TimePatterns/3=H:mm
+FormatData/es_CL/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_CL/TimePatterns/1=h:mm:ss a z
+FormatData/es_CL/TimePatterns/2=h:mm:ss a
+FormatData/es_CL/TimePatterns/3=h:mm a
+FormatData/es_EC/TimePatterns/0=h:mm:ss a zzzz
+FormatData/es_EC/TimePatterns/1=h:mm:ss a z
+FormatData/es_EC/TimePatterns/2=h:mm:ss a
+FormatData/es_EC/TimePatterns/3=h:mm a
# bug 8037343
FormatData/es_DO/DatePatterns/2=d MMM y
--- a/jdk/test/sun/text/resources/LocaleDataTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/text/resources/LocaleDataTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,7 +36,7 @@
* 6919624 6998391 7019267 7020960 7025837 7020583 7036905 7066203 7101495
* 7003124 7085757 7028073 7171028 7189611 8000983 7195759 8004489 8006509
* 7114053 7074882 7040556 8008577 8013836 8021121 6192407 6931564 8027695
- * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361
+ * 8017142 8037343 8055222 8042126 8074791 8075173 8080774 8129361 8134916
* @summary Verify locale data
* @run main LocaleDataTest
* @run main LocaleDataTest -cldr
@@ -149,6 +149,7 @@
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;
import java.util.MissingResourceException;
+import sun.util.resources.LocaleData;
public class LocaleDataTest
{
@@ -312,9 +313,7 @@
} else {
locale = new Locale(language, country, variant);
}
- ResourceBundle bundle = ResourceBundle.getBundle(fullName,
- locale,
- JRELocaleResourceBundleControl.INSTANCE);
+ ResourceBundle bundle = LocaleData.getBundle(fullName, locale);
resource = bundle.getObject(resTag);
}
catch (MissingResourceException e) {
@@ -368,51 +367,6 @@
}
return true;
}
-
- private static class JRELocaleResourceBundleControl extends ResourceBundle.Control {
- static final JRELocaleResourceBundleControl INSTANCE = new JRELocaleResourceBundleControl();
-
- private JRELocaleResourceBundleControl() {
- }
-
- @Override
- public Locale getFallbackLocale(String baseName, Locale locale) {
- if (baseName == null || locale == null) {
- throw new NullPointerException();
- }
- return null;
- }
-
- /**
- * Changes baseName to its per-language/country package name and
- * calls the super class implementation. For example,
- * if the baseName is "sun.text.resources.FormatData" and locale is ja_JP,
- * the baseName is changed to "sun.text.resources.ja.JP.FormatData". If
- * baseName contains "cldr", such as "sun.text.resources.cldr.FormatData",
- * the name is changed to "sun.text.resources.cldr.ja.JP.FormatData".
- */
- @Override
- public String toBundleName(String baseName, Locale locale) {
- String newBaseName = baseName;
- String lang = locale.getLanguage();
- String ctry = locale.getCountry();
- if (lang.length() > 0) {
- if (baseName.startsWith(UTIL_RESOURCES_PACKAGE + cldrSuffix)
- || baseName.startsWith(TEXT_RESOURCES_PACKAGE + cldrSuffix)) {
- // Assume the lengths are the same.
- if (UTIL_RESOURCES_PACKAGE.length()
- != TEXT_RESOURCES_PACKAGE.length()) {
- throw new InternalError("The resources package names have different lengths.");
- }
- int index = (TEXT_RESOURCES_PACKAGE + cldrSuffix).length();
- ctry = (ctry.length() == 2) ? ("." + ctry) : "";
- newBaseName = baseName.substring(0, index + 1) + lang + ctry
- + baseName.substring(index);
- }
- }
- return super.toBundleName(newBaseName, locale);
- }
- }
}
class EscapeReader extends FilterReader {
--- a/jdk/test/sun/tools/jinfo/JInfoSanityTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/tools/jinfo/JInfoSanityTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -71,7 +71,7 @@
String unknownHost = "Oja781nh2ev7vcvbajdg-Sda1-C";
OutputAnalyzer output = JInfoHelper.jinfoNoPid("med@" + unknownHost);
assertNotEquals(output.getExitValue(), 0, "A non-zero exit code should be returned for invalid operation");
- output.shouldContain("UnknownHostException: " + unknownHost);
+ output.shouldMatch(".*(Connection refused to host\\:|UnknownHostException\\:) " + unknownHost + ".*");
}
}
--- a/jdk/test/sun/tools/jps/TestJpsSanity.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/tools/jps/TestJpsSanity.java Wed Jan 06 14:54:24 2016 +0000
@@ -62,7 +62,7 @@
OutputAnalyzer output = JpsHelper.jps(invalidHostName);
Asserts.assertNotEquals(output.getExitValue(), 0, "Exit code shouldn't be 0");
Asserts.assertFalse(output.getStderr().isEmpty(), "Error output should not be empty");
- output.shouldContain("Unknown host: " + invalidHostName);
+ output.shouldMatch(".*(RMI Registry not available at|Unknown host\\:) " + invalidHostName + ".*");
}
}
--- a/jdk/test/sun/tools/jstatd/TestJstatdServer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/jdk/test/sun/tools/jstatd/TestJstatdServer.java Wed Jan 06 14:54:24 2016 +0000
@@ -24,6 +24,7 @@
/*
* @test
* @bug 4990825
+ * @key intermittent
* @library /lib/testlibrary
* @modules java.management
* @build jdk.testlibrary.* JstatdTest JstatGCUtilParser
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/Hello.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * This is a test program used in the test jjs-cpTest.sh.
+ */
+public class Hello {
+ public Hello() {}
+ public String getString() {
+ return "hello";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/args.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,21 @@
+/*
+ * This is the test JavaScript program used in jjs-argsTest.sh
+ */
+
+if (typeof(arguments) == 'undefined') {
+ throw new Error("arguments expected");
+}
+
+if (arguments.length != 2) {
+ throw new Error("2 arguments are expected here");
+}
+
+if (arguments[0] != 'hello') {
+ throw new Error("First arg should be 'hello'");
+}
+
+if (arguments[1] != 'world') {
+ throw new Error("Second arg should be 'world'");
+}
+
+print("Passed");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/classpath.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,8 @@
+/*
+ * This is the test JavaScript program used in jjs-cpTest.sh
+ */
+
+var v = new Packages.Hello();
+if (v.string != 'hello') {
+ throw new Error("Unexpected property value");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/common.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,66 @@
+#
+# 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.
+#
+
+#
+
+setup() {
+ # Verify directory context variables are set
+ if [ "${TESTJAVA}" = "" ] ; then
+ echo "TESTJAVA not set. Test cannot execute. Failed."
+ exit 1
+ fi
+
+ if [ "${TESTCLASSES}" = "" ] ; then
+ TESTCLASSES="."
+ fi
+
+ if [ "${TESTSRC}" = "" ] ; then
+ TESTSRC="."
+ fi
+
+ OS=`uname -s`
+ case ${OS} in
+ Windows_*)
+ PS=";"
+ FS="\\"
+ # MKS diff deals with trailing CRs automatically
+ golden_diff="diff"
+ ;;
+ CYGWIN*)
+ PS=":"
+ FS="/"
+ # Cygwin diff needs to be told to ignore trailing CRs
+ golden_diff="diff --strip-trailing-cr"
+ ;;
+ *)
+ PS=":"
+ FS="/"
+ # Assume any other platform doesn't have the trailing CR stuff
+ golden_diff="diff"
+ ;;
+ esac
+
+ JJS="${TESTJAVA}/bin/jjs"
+ JAVAC="${TESTJAVA}/bin/javac"
+ JAVA="${TESTJAVA}/bin/java"
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/es6.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,13 @@
+/*
+ * This is the test JavaScript program used in jjs-es6Test.sh
+ */
+
+const X = 4;
+try {
+ X = 55;
+ throw new Error("should have thrown TypeError");
+} catch (e) {
+ if (! (e instanceof TypeError)) {
+ throw new Error("TypeError expected, got " + e);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/file.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,47 @@
+/*
+ * This is the test JavaScript program used in jjs-fileTest.sh
+ */
+
+// good old 'hello world'!
+print('hello');
+
+// basic number manipulation
+var v = 2 + 5;
+v *= 5;
+v.doubleValue();
+v = v + " is the value";
+if (v != 0) {
+ print('yes v != 0');
+}
+
+// basic java access
+java.lang.System.out.println('hello world from script');
+
+// basic stream manipulation
+var al = new java.util.ArrayList();
+al.add("hello");
+al.add("world");
+// script functions for lambas
+al.stream().map(function(s) s.toUpperCase()).forEach(print);
+
+// interface implementation
+new java.lang.Runnable() {
+ run: function() {
+ print('I am runnable');
+ }
+}.run();
+
+// java class extension
+var MyList = Java.extend(java.util.ArrayList);
+var m = new MyList() {
+ size: function() {
+ print("size called");
+ // call super.size()
+ return Java.super(m).size();
+ }
+};
+
+print("is m an ArrayList? " + (m instanceof java.util.ArrayList));
+m.add("hello");
+m.add("world");
+print(m.size());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/file.out Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,9 @@
+hello
+yes v != 0
+hello world from script
+HELLO
+WORLD
+I am runnable
+is m an ArrayList? true
+size called
+2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-DTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-DTest.sh
+# Tests passing of Java system property by -D option
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+# test whether value specified by -D option is passed
+# to script as java.lang.System property.
+
+${JJS} -J-Djava.security.manager -J-Djava.security.policy=${TESTSRC}/sysprops.policy -Djjs.foo=bar ${TESTSRC}/sysprops.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-argsTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-argsTest.sh
+# Tests passing of script arguments from the command line
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+# we check whether args after "--" are passed as script arguments
+
+${JJS} -J-Djava.security.manager ${TESTSRC}/args.js -- hello world
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-cpTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-cpTest.sh
+# Tests -cp/-classpath option to set the classpath for jjs
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+rm -f Hello.class
+${JAVAC} ${TESTSRC}/Hello.java -d .
+
+# we check whether classpath setting for app classes
+# work with jjs. Script should be able to
+# access Java class "Hello".
+
+${JJS} -J-Djava.security.manager -cp . ${TESTSRC}/classpath.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+# -classpath and -cp are synonyms
+
+${JJS} -J-Djava.security.manager -classpath . ${TESTSRC}/classpath.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
+
+rm -f Hello.class
+echo "Passed"
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-es6Test.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-es6Test.sh
+# Tests ES6 language setting option '--language=es6'
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+${JJS} -J-Djava.security.manager --language=es6 ${TESTSRC}/es6.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-fileTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-fileTest.sh
+# Tests basic script file execution. Execute file.js and check output
+# against file.out file
+
+. ${TESTSRC-.}/common.sh
+
+setup
+rm -f jjs-fileTest.out 2>/dev/null
+${JJS} -J-Djava.security.manager ${TESTSRC}/file.js > jjs-fileTest.out 2>&1
+
+$golden_diff jjs-fileTest.out ${TESTSRC}/file.out
+if [ $? != 0 ]
+then
+ echo "Output of jjs file.js differ from expected output. Failed."
+ rm -f jjs-fileTest.out 2>/dev/null
+ exit 1
+fi
+
+rm -f jjs-fTest.out
+echo "Passed"
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-helpTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+#
+# Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-helpTest.sh
+# Tests that the output of 'jjs -help' is not empty
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+rm -f jjs-helpTest.out 2>/dev/null
+${JJS} -J-Djava.security.manager -help > jjs-helpTest.out 2>&1
+
+if [ ! -s jjs-helpTest.out ]
+then
+ echo "Output of jjs -help is empty. Failed."
+ rm -f jjs-helpTest.out 2>/dev/null
+ exit 1
+fi
+
+rm -f jjs-helpTest.out 2>/dev/null
+
+echo "Passed"
+exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-scriptingTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-scriptingTest.sh
+# Tests setting scripting mode via -scripting option
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+${JJS} -J-Djava.security.manager -scripting ${TESTSRC}/scripting.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/jjs-strictTest.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+#
+# 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.
+#
+
+
+# @test
+# @bug 8145750
+# @summary jjs fails to run simple scripts with security manager turned on
+# @run shell jjs-strictTest.sh
+# Tests basic ECMAScript strict mode setting via -strict option
+
+. ${TESTSRC-.}/common.sh
+
+setup
+
+${JJS} -J-Djava.security.manager -strict ${TESTSRC}/strict.js
+
+if [ $? -ne 0 ]; then
+ exit 1
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/scripting.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,18 @@
+/*
+ * This is the test JavaScript program used in jjs-scriptingTest.sh
+ */
+
+var str = <<END
+Multi line string
+works in scripting
+END
+
+var n = "Nashorn";
+var hello = "Hello, ${n}";
+if (hello != "Hello, Nashorn") {
+ throw new Error("string interpolation didn't work");
+}
+
+if (typeof readFully != "function") {
+ throw new Error("readFully is defined in -scripting");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/strict.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,12 @@
+/*
+ * This is the test JavaScript program used in jjs-strictTest.sh
+ */
+
+try {
+ v = "hello";
+ throw new Error("should have thrown ReferenceError");
+} catch (e) {
+ if (! (e instanceof ReferenceError)) {
+ throw new Error("ReferenceError expected, got " + e);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/sysprops.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,11 @@
+/*
+ * This is the test JavaScript program used in jjs-DTest.sh
+ */
+
+var Sys = java.lang.System;
+if (Sys.getProperty("jjs.foo") == "bar") {
+ print("Passed");
+} else {
+ // unexpected value
+ throw new Error("Unexpected System property value");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jjs/sysprops.policy Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,3 @@
+grant {
+ permission java.util.PropertyPermission "*", "read";
+};
--- a/langtools/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -340,3 +340,5 @@
c35ddcde581676275cfeff33e1a2b90b902593d9 jdk-9+95
d2a44416cba39957ea231eedc2fb8aad7be1b30c jdk-9+96
ae8cdc734bab4f19ef8babd2434dcf024672ad38 jdk-9+97
+345520da2ec17100cb512a53d541a307a195305e jdk-9+98
+cb73b474703e2de266542b505cffd658bcc052da jdk-9+99
--- a/langtools/make/tools/propertiesparser/parser/Message.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/make/tools/propertiesparser/parser/Message.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package propertiesparser.parser;
import java.util.ArrayList;
--- a/langtools/make/tools/propertiesparser/parser/MessageFile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/make/tools/propertiesparser/parser/MessageFile.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package propertiesparser.parser;
import java.io.*;
--- a/langtools/make/tools/propertiesparser/parser/MessageInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/make/tools/propertiesparser/parser/MessageInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package propertiesparser.parser;
import propertiesparser.parser.MessageType.CompoundType;
--- a/langtools/make/tools/propertiesparser/parser/MessageLine.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/make/tools/propertiesparser/parser/MessageLine.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package propertiesparser.parser;
import java.util.regex.Pattern;
--- a/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/java.compiler/share/classes/javax/tools/DocumentationTool.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package javax.tools;
import java.io.Writer;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/ErroneousTree.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/ErroneousTree.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.source.doctree;
import javax.tools.Diagnostic;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/UnknownBlockTagTree.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/UnknownBlockTagTree.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.source.doctree;
import java.util.List;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/UnknownInlineTagTree.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/doctree/UnknownInlineTagTree.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.source.doctree;
import java.util.List;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePathScanner.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/DocTreePathScanner.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.source.util;
import com.sun.source.doctree.DocTree;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/source/util/Plugin.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.source.util;
import java.util.ServiceLoader;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/ClientCodeWrapper.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javac.api;
import java.io.File;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/DiagnosticFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.api;
import java.util.Locale;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/AnnoConstruct.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/AnnoConstruct.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.code;
import java.lang.annotation.Annotation;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Wed Jan 06 14:54:24 2016 +0000
@@ -115,31 +115,23 @@
* called from MemberEnter.
*/
public void organizeTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) {
- annotate.afterTypes(new Runnable() {
- @Override
- public void run() {
- JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
-
- try {
- new TypeAnnotationPositions(true).scan(tree);
- } finally {
- log.useSource(oldSource);
- }
+ annotate.afterTypes(() -> {
+ JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
+ try {
+ new TypeAnnotationPositions(true).scan(tree);
+ } finally {
+ log.useSource(oldSource);
}
});
}
public void validateTypeAnnotationsSignatures(final Env<AttrContext> env, final JCClassDecl tree) {
- annotate.validate(new Runnable() { //validate annotations
- @Override
- public void run() {
- JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
-
- try {
- attr.validateTypeAnnotations(tree, true);
- } finally {
- log.useSource(oldSource);
- }
+ annotate.validate(() -> { //validate annotations
+ JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
+ try {
+ attr.validateTypeAnnotations(tree, true);
+ } finally {
+ log.useSource(oldSource);
}
});
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeMetadata.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeMetadata.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,7 +1,6 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights
- * reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE
- * HEADER.
+ * 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
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Wed Jan 06 14:54:24 2016 +0000
@@ -597,36 +597,42 @@
}
public Type removeWildcards(Type site) {
- Type capturedSite = capture(site);
- if (capturedSite != site) {
- Type formalInterface = site.tsym.type;
- ListBuffer<Type> typeargs = new ListBuffer<>();
- List<Type> actualTypeargs = site.getTypeArguments();
- List<Type> capturedTypeargs = capturedSite.getTypeArguments();
- //simply replace the wildcards with its bound
- for (Type t : formalInterface.getTypeArguments()) {
- if (actualTypeargs.head.hasTag(WILDCARD)) {
- WildcardType wt = (WildcardType)actualTypeargs.head;
- Type bound;
- switch (wt.kind) {
- case EXTENDS:
- case UNBOUND:
- CapturedType capVar = (CapturedType)capturedTypeargs.head;
- //use declared bound if it doesn't depend on formal type-args
- bound = capVar.bound.containsAny(capturedSite.getTypeArguments()) ?
- wt.type : capVar.bound;
- break;
- default:
- bound = wt.type;
+ if (site.getTypeArguments().stream().anyMatch(t -> t.hasTag(WILDCARD))) {
+ //compute non-wildcard parameterization - JLS 9.9
+ List<Type> actuals = site.getTypeArguments();
+ List<Type> formals = site.tsym.type.getTypeArguments();
+ ListBuffer<Type> targs = new ListBuffer<>();
+ for (Type formal : formals) {
+ Type actual = actuals.head;
+ Type bound = formal.getUpperBound();
+ if (actuals.head.hasTag(WILDCARD)) {
+ WildcardType wt = (WildcardType)actual;
+ //check that bound does not contain other formals
+ if (bound.containsAny(formals)) {
+ targs.add(wt.type);
+ } else {
+ //compute new type-argument based on declared bound and wildcard bound
+ switch (wt.kind) {
+ case UNBOUND:
+ targs.add(bound);
+ break;
+ case EXTENDS:
+ targs.add(glb(bound, wt.type));
+ break;
+ case SUPER:
+ targs.add(wt.type);
+ break;
+ default:
+ Assert.error("Cannot get here!");
+ }
}
- typeargs.append(bound);
} else {
- typeargs.append(actualTypeargs.head);
+ //not a wildcard - the new type argument remains unchanged
+ targs.add(actual);
}
- actualTypeargs = actualTypeargs.tail;
- capturedTypeargs = capturedTypeargs.tail;
+ actuals = actuals.tail;
}
- return subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList());
+ return subst(site.tsym.type, formals, targs.toList());
} else {
return site;
}
@@ -1436,12 +1442,13 @@
public boolean isCastable(Type t, Type s, Warner warn) {
if (t == s)
return true;
-
- if (t.isPrimitive() != s.isPrimitive())
+ if (t.isPrimitive() != s.isPrimitive()) {
+ t = skipTypeVars(t, false);
return (isConvertible(t, s, warn)
|| (allowObjectToPrimitiveCast &&
s.isPrimitive() &&
isSubtype(boxedClass(s).type, t)));
+ }
if (warn != warnStack.head) {
try {
warnStack = warnStack.prepend(warn);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Wed Jan 06 14:54:24 2016 +0000
@@ -223,53 +223,37 @@
s.resetAnnotations(); // mark Annotations as incomplete for now
- normal(new Runnable() {
- @Override
- public String toString() {
- return "Annotate " + annotations + " onto " + s + " in " + s.owner;
- }
+ normal(() -> {
+ Assert.check(s.annotationsPendingCompletion());
+ JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+ DiagnosticPosition prevLintPos =
+ deferPos != null
+ ? deferredLintHandler.setPos(deferPos)
+ : deferredLintHandler.immediate();
+ Lint prevLint = deferPos != null ? null : chk.setLint(lint);
+ try {
+ if (s.hasAnnotations() && annotations.nonEmpty())
+ log.error(annotations.head.pos, "already.annotated", Kinds.kindName(s), s);
- @Override
- public void run() {
- Assert.check(s.annotationsPendingCompletion());
- JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- DiagnosticPosition prevLintPos =
- deferPos != null
- ? deferredLintHandler.setPos(deferPos)
- : deferredLintHandler.immediate();
- Lint prevLint = deferPos != null ? null : chk.setLint(lint);
- try {
- if (s.hasAnnotations() && annotations.nonEmpty())
- log.error(annotations.head.pos, "already.annotated", Kinds.kindName(s), s);
+ Assert.checkNonNull(s, "Symbol argument to actualEnterAnnotations is null");
- Assert.checkNonNull(s, "Symbol argument to actualEnterAnnotations is null");
-
- // false is passed as fifth parameter since annotateLater is
- // never called for a type parameter
- annotateNow(s, annotations, localEnv, false, false);
- } finally {
- if (prevLint != null)
- chk.setLint(prevLint);
- deferredLintHandler.setPos(prevLintPos);
- log.useSource(prev);
- }
+ // false is passed as fifth parameter since annotateLater is
+ // never called for a type parameter
+ annotateNow(s, annotations, localEnv, false, false);
+ } finally {
+ if (prevLint != null)
+ chk.setLint(prevLint);
+ deferredLintHandler.setPos(prevLintPos);
+ log.useSource(prev);
}
});
- validate(new Runnable() { //validate annotations
- @Override
- public void run() {
- JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- try {
- chk.validateAnnotations(annotations, s);
- } finally {
- log.useSource(prev);
- }
- }
-
- @Override
- public String toString() {
- return "validate annotations: " + annotations + " on " + s;
+ validate(() -> { //validate annotations
+ JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+ try {
+ chk.validateAnnotations(annotations, s);
+ } finally {
+ log.useSource(prev);
}
});
}
@@ -279,42 +263,25 @@
public void annotateDefaultValueLater(JCExpression defaultValue, Env<AttrContext> localEnv,
MethodSymbol m, DiagnosticPosition deferPos)
{
- normal(new Runnable() {
- @Override
- public void run() {
- JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos);
- try {
- enterDefaultValue(defaultValue, localEnv, m);
- } finally {
- deferredLintHandler.setPos(prevLintPos);
- log.useSource(prev);
- }
- }
-
- @Override
- public String toString() {
- return "Annotate " + m.owner + "." +
- m + " default " + defaultValue;
+ normal(() -> {
+ JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+ DiagnosticPosition prevLintPos = deferredLintHandler.setPos(deferPos);
+ try {
+ enterDefaultValue(defaultValue, localEnv, m);
+ } finally {
+ deferredLintHandler.setPos(prevLintPos);
+ log.useSource(prev);
}
});
- validate(new Runnable() { //validate annotations
- @Override
- public void run() {
- JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
- try {
- // if default value is an annotation, check it is a well-formed
- // annotation value (e.g. no duplicate values, no missing values, etc.)
- chk.validateAnnotationTree(defaultValue);
- } finally {
- log.useSource(prev);
- }
- }
-
- @Override
- public String toString() {
- return "Validate default value " + m.owner + "." + m + " default " + defaultValue;
+ validate(() -> { //validate annotations
+ JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+ try {
+ // if default value is an annotation, check it is a well-formed
+ // annotation value (e.g. no duplicate values, no missing values, etc.)
+ chk.validateAnnotationTree(defaultValue);
+ } finally {
+ log.useSource(prev);
}
});
}
@@ -992,35 +959,17 @@
DiagnosticPosition deferPos)
{
Assert.checkNonNull(sym);
- normal(new Runnable() {
- @Override
- public String toString() {
- return "type annotate " + tree + " onto " + sym + " in " + sym.owner;
- }
-
- @Override
- public void run() {
- tree.accept(new TypeAnnotate(env, sym, deferPos));
- }
- });
+ normal(() -> tree.accept(new TypeAnnotate(env, sym, deferPos)));
}
/**
* Apply the annotations to the particular type.
*/
public void annotateTypeSecondStage(JCTree tree, List<JCAnnotation> annotations, Type storeAt) {
- typeAnnotation(new Runnable() {
- @Override
- public String toString() {
- return "Type annotate 2:nd stage " + annotations + " onto " + tree;
- }
-
- @Override
- public void run() {
- List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
- Assert.check(annotations.size() == compounds.size());
- storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
- }
+ typeAnnotation(() -> {
+ List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
+ Assert.check(annotations.size() == compounds.size());
+ storeAt.getMetadataOfKind(Kind.ANNOTATIONS).combine(new TypeMetadata.Annotations(compounds));
});
}
@@ -1028,17 +977,9 @@
* Apply the annotations to the particular type.
*/
public void annotateTypeParameterSecondStage(JCTree tree, List<JCAnnotation> annotations) {
- typeAnnotation(new Runnable() {
- @Override
- public String toString() {
- return "Type annotate 2:nd stage " + annotations + " onto " + tree;
- }
-
- @Override
- public void run() {
- List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
- Assert.check(annotations.size() == compounds.size());
- }
+ typeAnnotation(() -> {
+ List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
+ Assert.check(annotations.size() == compounds.size());
});
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrContext.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,7 @@
package com.sun.tools.javac.comp;
+import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Scope.WriteableScope;
@@ -95,6 +96,13 @@
*/
Type defaultSuperCallSite = null;
+ /** Tree that when non null, is to be preferentially used in diagnostics.
+ * Usually Env<AttrContext>.tree is the tree to be referred to in messages,
+ * but this may not be true during the window a method is looked up in enclosing
+ * contexts (JDK-8145466)
+ */
+ JCTree preferredTreeForDiagnostics;
+
/** Duplicate this context, replacing scope field and copying all others.
*/
AttrContext dup(WriteableScope scope) {
@@ -112,6 +120,7 @@
info.isSpeculative = isSpeculative;
info.isAnonymousDiamond = isAnonymousDiamond;
info.isNewClass = isNewClass;
+ info.preferredTreeForDiagnostics = preferredTreeForDiagnostics;
return info;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/InferenceContext.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,6 +29,7 @@
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -78,7 +79,7 @@
/** list of inference vars in this context */
List<Type> inferencevars;
- Map<FreeTypeListener, List<Type>> freeTypeListeners = new HashMap<>();
+ Map<FreeTypeListener, List<Type>> freeTypeListeners = new LinkedHashMap<>();
Types types;
Infer infer;
@@ -263,7 +264,7 @@
void notifyChange(List<Type> inferredVars) {
InferenceException thrownEx = null;
for (Map.Entry<FreeTypeListener, List<Type>> entry :
- new HashMap<>(freeTypeListeners).entrySet()) {
+ new LinkedHashMap<>(freeTypeListeners).entrySet()) {
if (!Type.containsAny(entry.getValue(), inferencevars.diff(inferredVars))) {
try {
entry.getKey().typesInferred(this);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.comp;
import com.sun.tools.javac.tree.*;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Wed Jan 06 14:54:24 2016 +0000
@@ -2707,11 +2707,11 @@
if (fvs.nonEmpty()) {
List<Type> addedargtypes = List.nil();
for (List<VarSymbol> l = fvs; l.nonEmpty(); l = l.tail) {
+ final Name pName = proxyName(l.head.name);
+ m.capturedLocals =
+ m.capturedLocals.prepend((VarSymbol)
+ (proxies.findFirst(pName)));
if (TreeInfo.isInitialConstructor(tree)) {
- final Name pName = proxyName(l.head.name);
- m.capturedLocals =
- m.capturedLocals.append((VarSymbol)
- (proxies.findFirst(pName)));
added = added.prepend(
initField(tree.body.pos, pName));
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jan 06 14:54:24 2016 +0000
@@ -722,7 +722,8 @@
Warner warn) {
//should we expand formals?
boolean useVarargs = deferredAttrContext.phase.isVarargsRequired();
- List<JCExpression> trees = TreeInfo.args(env.tree);
+ JCTree callTree = treeForDiagnostics(env);
+ List<JCExpression> trees = TreeInfo.args(callTree);
//inference context used during this method check
InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
@@ -731,7 +732,7 @@
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
- reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+ reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
@@ -743,7 +744,7 @@
}
if (formals.head != varargsFormal) {
- reportMC(env.tree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
+ reportMC(callTree, MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
if (useVarargs) {
@@ -759,6 +760,11 @@
}
}
+ // where
+ private JCTree treeForDiagnostics(Env<AttrContext> env) {
+ return env.info.preferredTreeForDiagnostics != null ? env.info.preferredTreeForDiagnostics : env.tree;
+ }
+
/**
* Does the actual argument conforms to the corresponding formal?
*/
@@ -1847,17 +1853,23 @@
boolean staticOnly = false;
while (env1.outer != null) {
if (isStatic(env1)) staticOnly = true;
- Symbol sym = findMethod(
- env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
- allowBoxing, useVarargs);
- if (sym.exists()) {
- if (staticOnly &&
- sym.kind == MTH &&
- sym.owner.kind == TYP &&
- (sym.flags() & STATIC) == 0) return new StaticError(sym);
- else return sym;
- } else {
- bestSoFar = bestOf(bestSoFar, sym);
+ Assert.check(env1.info.preferredTreeForDiagnostics == null);
+ env1.info.preferredTreeForDiagnostics = env.tree;
+ try {
+ Symbol sym = findMethod(
+ env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
+ allowBoxing, useVarargs);
+ if (sym.exists()) {
+ if (staticOnly &&
+ sym.kind == MTH &&
+ sym.owner.kind == TYP &&
+ (sym.flags() & STATIC) == 0) return new StaticError(sym);
+ else return sym;
+ } else {
+ bestSoFar = bestOf(bestSoFar, sym);
+ }
+ } finally {
+ env1.info.preferredTreeForDiagnostics = null;
}
if ((env1.enclClass.sym.flags() & STATIC) != 0) staticOnly = true;
env1 = env1.outer;
@@ -4184,7 +4196,11 @@
DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
DiagnosticType preferredKind, JCDiagnostic d) {
JCDiagnostic cause = (JCDiagnostic)d.getArgs()[causeIndex];
- return diags.create(preferredKind, preferredSource, d.getDiagnosticPosition(),
+ DiagnosticPosition pos = d.getDiagnosticPosition();
+ if (pos == null) {
+ pos = preferedPos;
+ }
+ return diags.create(preferredKind, preferredSource, pos,
"prob.found.req", cause);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.file;
import java.io.IOException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.file;
import java.io.File;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Profile.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.jvm;
import com.sun.tools.javac.util.Context;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.main;
import java.io.File;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Parser.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/Parser.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javac.parser;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.platform;
import java.io.IOException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformDescription.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformDescription.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.platform;
import java.io.Closeable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformProvider.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.platform;
/** A collection of platform descriptions that can be selected using {@code -release name}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformUtils.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/PlatformUtils.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.platform;
import com.sun.tools.javac.main.Arguments;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/sym/Profiles.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.sym;
import java.io.BufferedInputStream;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocCommentTable.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocCommentTable.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.tree;
import com.sun.source.doctree.ErroneousTree;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.util;
import java.nio.file.Path;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ForwardingDiagnosticFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/ForwardingDiagnosticFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.util;
import java.util.Set;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.util;
import java.util.Iterator;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.util;
import java.util.Collection;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javac.util;
import java.nio.file.Path;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/LLNI.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/LLNI.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javah;
import java.io.OutputStream;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/Mangle.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/Mangle.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javah;
import javax.lang.model.element.ExecutableElement;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/TypeSignature.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/TypeSignature.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javah;
import java.util.*;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/Util.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/Util.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.javah;
import java.io.PrintWriter;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/PubApiExtractor.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/PortFileInaccessibleException.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/PortFileInaccessibleException.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.client;
import java.io.IOException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/FileObjectWithLocation.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/FileObjectWithLocation.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import javax.tools.FileObject;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaFileObjectWithLocation.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/JavaFileObjectWithLocation.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import javax.tools.ForwardingJavaFileObject;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PathAndPackageVerifier.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PathAndPackageVerifier.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import java.nio.file.Path;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import java.io.Writer;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import java.io.IOException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.comp;
import java.io.*;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ArrayTypeDesc.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ArrayTypeDesc.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PrimitiveTypeDesc.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PrimitiveTypeDesc.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApi.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubApi.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubMethod.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubMethod.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubType.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubVar.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/PubVar.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ReferenceTypeDesc.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/ReferenceTypeDesc.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeDesc.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeDesc.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeVarTypeDesc.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/pubapi/TypeVarTypeDesc.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.pubapi;
import java.io.Serializable;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
import java.io.Writer;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
import java.io.IOException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
import java.io.Writer;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
import java.io.FileNotFoundException;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Terminable.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.sjavac.server;
/**
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractProfileIndexWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.formats.html;
import java.io.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.doclets.formats.html;
import com.sun.javadoc.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.doclets.internal.toolkit;
import java.io.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ClassWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.doclets.internal.toolkit;
import java.io.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfilePackageSummaryWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/ProfileSummaryWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/builders/LayoutParser.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.builders;
import java.io.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/CodeTaglet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.taglets;
import java.util.Map;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/IndexTaglet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.taglets;
import java.util.Map;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LiteralTaglet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.taglets;
import java.util.Map;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/MessageRetriever.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.util;
import java.text.MessageFormat;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/TextTag.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.doclets.internal.toolkit.util;
import com.sun.javadoc.*;
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/api/JavadocTaskImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javadoc.api;
import com.sun.tools.javac.util.ClientCodeException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -24,6 +23,7 @@
* questions.
*/
+
package com.sun.tools.classfile;
import java.io.ByteArrayOutputStream;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/CompilationID_attribute.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.classfile;
import java.io.IOException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPoolException.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.classfile;
/*
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.classfile;
import java.util.Deque;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Descriptor.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.classfile;
import java.io.IOException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/DescriptorException.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package com.sun.tools.classfile;
/*
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/EnclosingMethod_attribute.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -24,6 +23,7 @@
* questions.
*/
+
package com.sun.tools.classfile;
import java.io.IOException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/classfile/SourceID_attribute.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.classfile;
import java.io.IOException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/javap/TypeAnnotationWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.javap;
import com.sun.tools.classfile.Attribute;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import java.io.PrintStream;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Archive.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import com.sun.tools.classfile.ClassFile;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ClassFileReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import com.sun.tools.classfile.ClassFile;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import com.sun.tools.classfile.AccessFlags;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import java.util.Collections;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModulesXmlReader.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import java.io.IOException;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import com.sun.tools.classfile.ClassFile;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package com.sun.tools.jdeps;
import java.io.IOException;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/remote/RemoteCodes.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,6 @@
* questions.
*/
-
package jdk.internal.jshell.remote;
import java.util.regex.Pattern;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/EditingHistory.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/EditingHistory.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.internal.jshell.tool;
import java.util.ArrayList;
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/StopDetectingInputStream.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/StopDetectingInputStream.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.internal.jshell.tool;
import java.io.IOException;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/DeclarationSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.Collection;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ErroneousSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ErroneousSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import jdk.jshell.Key.ErroneousKey;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.ArrayList;
@@ -189,7 +190,7 @@
private List<SnippetEvent> processVariables(String userSource, List<? extends Tree> units, String compileSource, ParseTask pt) {
List<SnippetEvent> allEvents = new ArrayList<>();
- TreeDissector dis = new TreeDissector(pt);
+ TreeDissector dis = TreeDissector.createByFirstClass(pt);
for (Tree unitTree : units) {
VariableTree vt = (VariableTree) unitTree;
String name = vt.getName().toString();
@@ -294,7 +295,7 @@
TreeDependencyScanner tds = new TreeDependencyScanner();
tds.scan(unitTree);
- TreeDissector dis = new TreeDissector(pt);
+ TreeDissector dis = TreeDissector.createByFirstClass(pt);
ClassTree klassTree = (ClassTree) unitTree;
String name = klassTree.getSimpleName().toString();
@@ -353,7 +354,7 @@
tds.scan(unitTree);
MethodTree mt = (MethodTree) unitTree;
- TreeDissector dis = new TreeDissector(pt);
+ TreeDissector dis = TreeDissector.createByFirstClass(pt);
DiagList modDiag = modifierDiagnostics(mt.getModifiers(), dis, true);
if (modDiag.hasErrors()) {
return compileFailResult(modDiag, userSource);
@@ -417,8 +418,8 @@
private ExpressionInfo typeOfExpression(String expression) {
Wrap guts = Wrap.methodReturnWrap(expression);
TaskFactory.AnalyzeTask at = trialCompile(guts);
- if (!at.hasErrors() && at.cuTree() != null) {
- return new TreeDissector(at)
+ if (!at.hasErrors() && at.firstCuTree() != null) {
+ return TreeDissector.createByFirstClass(at)
.typeOfReturnStatement(at.messages(), state.maps::fullClassNameAndPackageToClass);
}
return null;
@@ -512,13 +513,17 @@
ins.stream().forEach(u -> u.initialize(ins));
AnalyzeTask at = state.taskFactory.new AnalyzeTask(ins);
ins.stream().forEach(u -> u.setDiagnostics(at));
+
// corral any Snippets that need it
- if (ins.stream().filter(u -> u.corralIfNeeded(ins)).count() > 0) {
+ AnalyzeTask cat;
+ if (ins.stream().anyMatch(u -> u.corralIfNeeded(ins))) {
// if any were corralled, re-analyze everything
- AnalyzeTask cat = state.taskFactory.new AnalyzeTask(ins);
+ cat = state.taskFactory.new AnalyzeTask(ins);
ins.stream().forEach(u -> u.setCorralledDiagnostics(cat));
+ } else {
+ cat = at;
}
- ins.stream().forEach(u -> u.setStatus());
+ ins.stream().forEach(u -> u.setStatus(cat));
// compile and load the legit snippets
boolean success;
while (true) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,6 +33,7 @@
import java.net.Socket;
import com.sun.jdi.*;
import java.io.EOFException;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jdk.jshell.ClassTracker.ClassInfo;
@@ -247,17 +248,18 @@
//MessageOutput.textResources = ResourceBundle.getBundle("impl.TTYResources",
// Locale.getDefault());
- String connect = "com.sun.jdi.CommandLineLaunch:";
- String cmdLine = "jdk.internal.jshell.remote.RemoteAgent";
+ String connectorName = "com.sun.jdi.CommandLineLaunch";
String classPath = System.getProperty("java.class.path");
String bootclassPath = System.getProperty("sun.boot.class.path");
- String javaArgs = "-classpath " + classPath + " -Xbootclasspath:" + bootclassPath;
+ String javaArgs = "-classpath \"" + classPath + "\" -Xbootclasspath:\"" + bootclassPath + "\"";
+ Map<String, String> argumentName2Value = new HashMap<>();
+ argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port);
+ argumentName2Value.put("options", javaArgs);
- String connectSpec = connect + "main=" + cmdLine + " " + port + ",options=" + javaArgs + ",";
boolean launchImmediately = true;
int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS;
- env.init(connectSpec, launchImmediately, traceFlags);
+ env.init(connectorName, argumentName2Value, launchImmediately, traceFlags);
if (env.connection().isOpen() && env.vm().canBeModified()) {
/*
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExpressionSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExpressionSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import jdk.jshell.Key.ExpressionKey;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ImportSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import jdk.jshell.Key.ImportKey;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIConnection.java Wed Jan 06 14:54:24 2016 +0000
@@ -38,8 +38,9 @@
import com.sun.jdi.connect.*;
import java.util.*;
-import java.util.regex.*;
+import java.util.Map.Entry;
import java.io.*;
+
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
/**
@@ -83,239 +84,35 @@
return null;
}
- private Map <String, com.sun.jdi.connect.Connector.Argument> parseConnectorArgs(Connector connector, String argString) {
- Map<String, com.sun.jdi.connect.Connector.Argument> arguments = connector.defaultArguments();
+ private Map <String, Connector.Argument> mergeConnectorArgs(Connector connector, Map<String, String> argumentName2Value) {
+ Map<String, Connector.Argument> arguments = connector.defaultArguments();
- /*
- * We are parsing strings of the form:
- * name1=value1,[name2=value2,...]
- * However, the value1...valuen substrings may contain
- * embedded comma(s), so make provision for quoting inside
- * the value substrings. (Bug ID 4285874)
- */
- String regexPattern =
- "(quote=[^,]+,)|" + // special case for quote=.,
- "(\\w+=)" + // name=
- "(((\"[^\"]*\")|" + // ( "l , ue"
- "('[^']*')|" + // 'l , ue'
- "([^,'\"]+))+,)"; // v a l u e )+ ,
- Pattern p = Pattern.compile(regexPattern);
- Matcher m = p.matcher(argString);
- while (m.find()) {
- int startPosition = m.start();
- int endPosition = m.end();
- if (startPosition > 0) {
- /*
- * It is an error if parsing skips over any part of argString.
- */
- throw new IllegalArgumentException("Illegal connector argument" +
- argString);
- }
+ for (Entry<String, String> argumentEntry : argumentName2Value.entrySet()) {
+ String name = argumentEntry.getKey();
+ String value = argumentEntry.getValue();
+ Connector.Argument argument = arguments.get(name);
- String token = argString.substring(startPosition, endPosition);
- int index = token.indexOf('=');
- String name = token.substring(0, index);
- String value = token.substring(index + 1,
- token.length() - 1); // Remove comma delimiter
-
- /*
- * for values enclosed in quotes (single and/or double quotes)
- * strip off enclosing quote chars
- * needed for quote enclosed delimited substrings
- */
- if (name.equals("options")) {
- StringBuilder sb = new StringBuilder();
- for (String s : splitStringAtNonEnclosedWhiteSpace(value)) {
- while (isEnclosed(s, "\"") || isEnclosed(s, "'")) {
- s = s.substring(1, s.length() - 1);
- }
- sb.append(s);
- sb.append(" ");
- }
- value = sb.toString();
- }
-
- Connector.Argument argument = arguments.get(name);
if (argument == null) {
throw new IllegalArgumentException("Argument is not defined for connector:" +
name + " -- " + connector.name());
}
+
argument.setValue(value);
-
- argString = argString.substring(endPosition); // Remove what was just parsed...
- m = p.matcher(argString); // and parse again on what is left.
}
- if ((! argString.equals(",")) && (argString.length() > 0)) {
- /*
- * It is an error if any part of argString is left over,
- * unless it was empty to begin with.
- */
- throw new IllegalArgumentException("Illegal connector argument" + argString);
- }
+
return arguments;
}
- private static boolean isEnclosed(String value, String enclosingChar) {
- if (value.indexOf(enclosingChar) == 0) {
- int lastIndex = value.lastIndexOf(enclosingChar);
- if (lastIndex > 0 && lastIndex == value.length() - 1) {
- return true;
- }
- }
- return false;
- }
+ JDIConnection(JDIEnv env, String connectorName, Map<String, String> argumentName2Value, int traceFlags, JShell proc) {
+ this.env = env;
+ this.proc = proc;
+ this.connector = findConnector(connectorName);
- private static List<String> splitStringAtNonEnclosedWhiteSpace(String value) throws IllegalArgumentException {
- List<String> al = new ArrayList<>();
- char[] arr;
- int startPosition = 0;
- int endPosition;
- final char SPACE = ' ';
- final char DOUBLEQ = '"';
- final char SINGLEQ = '\'';
-
- /*
- * An "open" or "active" enclosing state is where
- * the first valid start quote qualifier is found,
- * and there is a search in progress for the
- * relevant end matching quote
- *
- * enclosingTargetChar set to SPACE
- * is used to signal a non open enclosing state
- */
- char enclosingTargetChar = SPACE;
-
- if (value == null) {
- throw new IllegalArgumentException("value string is null");
+ if (connector == null) {
+ throw new IllegalArgumentException("No connector named: " + connectorName);
}
- // split parameter string into individual chars
- arr = value.toCharArray();
-
- for (int i = 0; i < arr.length; i++) {
- switch (arr[i]) {
- case SPACE: {
- // do nothing for spaces
- // unless last in array
- if (isLastChar(arr, i)) {
- endPosition = i;
- // break for substring creation
- break;
- }
- continue;
- }
- case DOUBLEQ:
- case SINGLEQ: {
- if (enclosingTargetChar == arr[i]) {
- // potential match to close open enclosing
- if (isNextCharWhitespace(arr, i)) {
- // if peek next is whitespace
- // then enclosing is a valid substring
- endPosition = i;
- // reset enclosing target char
- enclosingTargetChar = SPACE;
- // break for substring creation
- break;
- }
- }
- if (enclosingTargetChar == SPACE) {
- // no open enclosing state
- // handle as normal char
- if (isPreviousCharWhitespace(arr, i)) {
- startPosition = i;
- // peek forward for end candidates
- if (value.indexOf(arr[i], i + 1) >= 0) {
- // set open enclosing state by
- // setting up the target char
- enclosingTargetChar = arr[i];
- } else {
- // no more target chars left to match
- // end enclosing, handle as normal char
- if (isNextCharWhitespace(arr, i)) {
- endPosition = i;
- // break for substring creation
- break;
- }
- }
- }
- }
- continue;
- }
- default: {
- // normal non-space, non-" and non-' chars
- if (enclosingTargetChar == SPACE) {
- // no open enclosing state
- if (isPreviousCharWhitespace(arr, i)) {
- // start of space delim substring
- startPosition = i;
- }
- if (isNextCharWhitespace(arr, i)) {
- // end of space delim substring
- endPosition = i;
- // break for substring creation
- break;
- }
- }
- continue;
- }
- }
-
- // break's end up here
- if (startPosition > endPosition) {
- throw new IllegalArgumentException("Illegal option values");
- }
-
- // extract substring and add to List<String>
- al.add(value.substring(startPosition, ++endPosition));
-
- // set new start position
- i = startPosition = endPosition;
-
- } // for loop
-
- return al;
- }
-
- static private boolean isPreviousCharWhitespace(char[] arr, int curr_pos) {
- return isCharWhitespace(arr, curr_pos - 1);
- }
-
- static private boolean isNextCharWhitespace(char[] arr, int curr_pos) {
- return isCharWhitespace(arr, curr_pos + 1);
- }
-
- static private boolean isCharWhitespace(char[] arr, int pos) {
- if (pos < 0 || pos >= arr.length) {
- // outside arraybounds is considered an implicit space
- return true;
- }
- return (arr[pos] == ' ');
- }
-
- static private boolean isLastChar(char[] arr, int pos) {
- return (pos + 1 == arr.length);
- }
-
- JDIConnection(JDIEnv env, String connectSpec, int traceFlags, JShell proc) {
- this.env = env;
- this.proc = proc;
- String nameString;
- String argString;
- int index = connectSpec.indexOf(':');
- if (index == -1) {
- nameString = connectSpec;
- argString = "";
- } else {
- nameString = connectSpec.substring(0, index);
- argString = connectSpec.substring(index + 1);
- }
-
- connector = findConnector(nameString);
- if (connector == null) {
- throw new IllegalArgumentException("No connector named: " + nameString);
- }
-
- connectorArgs = parseConnectorArgs(connector, argString);
+ connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
this.traceFlags = traceFlags;
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEnv.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEnv.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,8 @@
package jdk.jshell;
+import java.util.Map;
+
import com.sun.jdi.*;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
@@ -41,8 +43,8 @@
this.state = state;
}
- void init(String connectSpec, boolean openNow, int flags) {
- connection = new JDIConnection(this, connectSpec, flags, state);
+ void init(String connectorName, Map<String, String> argumentName2Value, boolean openNow, int flags) {
+ connection = new JDIConnection(this, connectorName, argumentName2Value, flags, state);
if (!connection.isLaunch() || openNow) {
connection.open();
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEventHandler.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JDIEventHandler.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.Set;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MethodSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MethodSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.Collection;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/OuterWrap.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import jdk.jshell.Wrap.CompoundWrap;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/PersistentSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
/**
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParser.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import com.sun.tools.javac.code.TypeTag;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ReplParserFactory.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import com.sun.tools.javac.parser.JavacParser;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java Wed Jan 06 14:54:24 2016 +0000
@@ -239,7 +239,7 @@
private List<Suggestion> computeSuggestions(OuterWrap code, int cursor, int[] anchor) {
AnalyzeTask at = proc.taskFactory.new AnalyzeTask(code);
SourcePositions sp = at.trees().getSourcePositions();
- CompilationUnitTree topLevel = at.cuTree();
+ CompilationUnitTree topLevel = at.firstCuTree();
List<Suggestion> result = new ArrayList<>();
TreePath tp = pathFor(topLevel, sp, code.snippetIndexToWrapIndex(cursor));
if (tp != null) {
@@ -976,7 +976,7 @@
OuterWrap codeWrap = wrapInClass(Wrap.methodWrap(code));
AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap);
SourcePositions sp = at.trees().getSourcePositions();
- CompilationUnitTree topLevel = at.cuTree();
+ CompilationUnitTree topLevel = at.firstCuTree();
TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(cursor));
if (tp == null)
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/StatementSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/StatementSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import jdk.jshell.Key.StatementKey;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java Wed Jan 06 14:54:24 2016 +0000
@@ -56,6 +56,7 @@
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
+import static java.util.stream.Collectors.toList;
import java.util.stream.Stream;
import javax.lang.model.util.Elements;
import javax.tools.FileObject;
@@ -196,7 +197,7 @@
*/
class ParseTask extends BaseTask {
- private final CompilationUnitTree cut;
+ private final Iterable<? extends CompilationUnitTree> cuts;
private final List<? extends Tree> units;
ParseTask(final String source) {
@@ -204,16 +205,13 @@
new StringSourceHandler(),
"-XDallowStringFolding=false", "-proc:none");
ReplParserFactory.instance(getContext());
- Iterable<? extends CompilationUnitTree> asts = parse();
- Iterator<? extends CompilationUnitTree> it = asts.iterator();
- if (it.hasNext()) {
- this.cut = it.next();
- List<? extends ImportTree> imps = cut.getImports();
- this.units = !imps.isEmpty() ? imps : cut.getTypeDecls();
- } else {
- this.cut = null;
- this.units = Collections.emptyList();
- }
+ cuts = parse();
+ units = Util.stream(cuts)
+ .flatMap(cut -> {
+ List<? extends ImportTree> imps = cut.getImports();
+ return (!imps.isEmpty() ? imps : cut.getTypeDecls()).stream();
+ })
+ .collect(toList());
}
private Iterable<? extends CompilationUnitTree> parse() {
@@ -229,8 +227,8 @@
}
@Override
- CompilationUnitTree cuTree() {
- return cut;
+ Iterable<? extends CompilationUnitTree> cuTrees() {
+ return cuts;
}
}
@@ -239,7 +237,7 @@
*/
class AnalyzeTask extends BaseTask {
- private final CompilationUnitTree cut;
+ private final Iterable<? extends CompilationUnitTree> cuts;
AnalyzeTask(final OuterWrap wrap) {
this(Stream.of(wrap),
@@ -255,14 +253,7 @@
<T>AnalyzeTask(final Stream<T> stream, SourceHandler<T> sourceHandler,
String... extraOptions) {
super(stream, sourceHandler, extraOptions);
- Iterator<? extends CompilationUnitTree> cuts = analyze().iterator();
- if (cuts.hasNext()) {
- this.cut = cuts.next();
- //proc.debug("AnalyzeTask element=%s cutp=%s cut=%s\n", e, cutp, cut);
- } else {
- this.cut = null;
- //proc.debug("AnalyzeTask -- no elements -- %s\n", getDiagnostics());
- }
+ cuts = analyze();
}
private Iterable<? extends CompilationUnitTree> analyze() {
@@ -276,8 +267,8 @@
}
@Override
- CompilationUnitTree cuTree() {
- return cut;
+ Iterable<? extends CompilationUnitTree> cuTrees() {
+ return cuts;
}
Elements getElements() {
@@ -332,7 +323,7 @@
}
@Override
- CompilationUnitTree cuTree() {
+ Iterable<? extends CompilationUnitTree> cuTrees() {
throw new UnsupportedOperationException("Not supported.");
}
}
@@ -362,7 +353,11 @@
compilationUnits, context);
}
- abstract CompilationUnitTree cuTree();
+ abstract Iterable<? extends CompilationUnitTree> cuTrees();
+
+ CompilationUnitTree firstCuTree() {
+ return cuTrees().iterator().next();
+ }
Diag diag(Diagnostic<? extends JavaFileObject> diag) {
return sourceHandler.diag(diag);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java Wed Jan 06 14:54:24 2016 +0000
@@ -48,7 +48,10 @@
import java.util.List;
import java.util.Locale;
import java.util.function.BinaryOperator;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
import javax.lang.model.type.TypeMirror;
+import jdk.jshell.Util.Pair;
/**
* Utilities for analyzing compiler API parse trees.
@@ -68,23 +71,48 @@
}
private final TaskFactory.BaseTask bt;
- private ClassTree firstClass;
+ private final ClassTree targetClass;
+ private final CompilationUnitTree targetCompilationUnit;
private SourcePositions theSourcePositions = null;
- TreeDissector(TaskFactory.BaseTask bt) {
+ private TreeDissector(TaskFactory.BaseTask bt, CompilationUnitTree targetCompilationUnit, ClassTree targetClass) {
this.bt = bt;
+ this.targetCompilationUnit = targetCompilationUnit;
+ this.targetClass = targetClass;
+ }
+
+ static TreeDissector createByFirstClass(TaskFactory.BaseTask bt) {
+ Pair<CompilationUnitTree, ClassTree> pair = classes(bt.firstCuTree())
+ .findFirst().orElseGet(() -> new Pair<>(bt.firstCuTree(), null));
+
+ return new TreeDissector(bt, pair.first, pair.second);
}
+ private static final Predicate<? super Tree> isClassOrInterface =
+ t -> t.getKind() == Tree.Kind.CLASS || t.getKind() == Tree.Kind.INTERFACE;
- ClassTree firstClass() {
- if (firstClass == null) {
- firstClass = computeFirstClass();
- }
- return firstClass;
+ private static Stream<Pair<CompilationUnitTree, ClassTree>> classes(CompilationUnitTree cut) {
+ return cut == null
+ ? Stream.empty()
+ : cut.getTypeDecls().stream()
+ .filter(isClassOrInterface)
+ .map(decl -> new Pair<>(cut, (ClassTree)decl));
}
- CompilationUnitTree cuTree() {
- return bt.cuTree();
+ private static Stream<Pair<CompilationUnitTree, ClassTree>> classes(Iterable<? extends CompilationUnitTree> cuts) {
+ return Util.stream(cuts)
+ .flatMap(TreeDissector::classes);
+ }
+
+ static TreeDissector createBySnippet(TaskFactory.BaseTask bt, Snippet si) {
+ String name = si.className();
+
+ Pair<CompilationUnitTree, ClassTree> pair = classes(bt.cuTrees())
+ .filter(p -> p.second.getSimpleName().contentEquals(name))
+ .findFirst().orElseThrow(() ->
+ new IllegalArgumentException("Class " + name + " is not found."));
+
+ return new TreeDissector(bt, pair.first, pair.second);
}
Types types() {
@@ -103,11 +131,11 @@
}
int getStartPosition(Tree tree) {
- return (int) getSourcePositions().getStartPosition(cuTree(), tree);
+ return (int) getSourcePositions().getStartPosition(targetCompilationUnit, tree);
}
int getEndPosition(Tree tree) {
- return (int) getSourcePositions().getEndPosition(cuTree(), tree);
+ return (int) getSourcePositions().getEndPosition(targetCompilationUnit, tree);
}
Range treeToRange(Tree tree) {
@@ -134,9 +162,9 @@
}
Tree firstClassMember() {
- if (firstClass() != null) {
+ if (targetClass != null) {
//TODO: missing classes
- for (Tree mem : firstClass().getMembers()) {
+ for (Tree mem : targetClass.getMembers()) {
if (mem.getKind() == Tree.Kind.VARIABLE) {
return mem;
}
@@ -152,8 +180,8 @@
}
StatementTree firstStatement() {
- if (firstClass() != null) {
- for (Tree mem : firstClass().getMembers()) {
+ if (targetClass != null) {
+ for (Tree mem : targetClass.getMembers()) {
if (mem.getKind() == Tree.Kind.METHOD) {
MethodTree mt = (MethodTree) mem;
if (isDoIt(mt.getName())) {
@@ -169,8 +197,8 @@
}
VariableTree firstVariable() {
- if (firstClass() != null) {
- for (Tree mem : firstClass().getMembers()) {
+ if (targetClass != null) {
+ for (Tree mem : targetClass.getMembers()) {
if (mem.getKind() == Tree.Kind.VARIABLE) {
VariableTree vt = (VariableTree) mem;
return vt;
@@ -180,17 +208,6 @@
return null;
}
- private ClassTree computeFirstClass() {
- if (cuTree() == null) {
- return null;
- }
- for (Tree decl : cuTree().getTypeDecls()) {
- if (decl.getKind() == Tree.Kind.CLASS || decl.getKind() == Tree.Kind.INTERFACE) {
- return (ClassTree) decl;
- }
- }
- return null;
- }
ExpressionInfo typeOfReturnStatement(JavacMessages messages, BinaryOperator<String> fullClassNameAndPackageToClass) {
ExpressionInfo ei = new ExpressionInfo();
@@ -198,7 +215,7 @@
if (unitTree instanceof ReturnTree) {
ei.tree = ((ReturnTree) unitTree).getExpression();
if (ei.tree != null) {
- TreePath viPath = trees().getPath(cuTree(), ei.tree);
+ TreePath viPath = trees().getPath(targetCompilationUnit, ei.tree);
if (viPath != null) {
TypeMirror tm = trees().getTypeMirror(viPath);
if (tm != null) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypeDeclSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypeDeclSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.Collection;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TypePrinter.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,15 +41,15 @@
* Print types in source form.
*/
class TypePrinter extends Printer {
+ private static final String OBJECT = "Object";
private final JavacMessages messages;
private final BinaryOperator<String> fullClassNameAndPackageToClass;
- private final Type typeToPrint;
+ private boolean useWildCard = false;
TypePrinter(JavacMessages messages, BinaryOperator<String> fullClassNameAndPackageToClass, Type typeToPrint) {
this.messages = messages;
this.fullClassNameAndPackageToClass = fullClassNameAndPackageToClass;
- this.typeToPrint = typeToPrint;
}
@Override
@@ -64,21 +64,40 @@
@Override
public String visitCapturedType(Type.CapturedType t, Locale locale) {
- if (t == typeToPrint) {
- return visit(t.getUpperBound(), locale);
- } else {
- return visit(t.wildcard, locale);
+ return visit(t.wildcard, locale);
+ }
+
+ @Override
+ public String visitWildcardType(Type.WildcardType wt, Locale locale) {
+ if (useWildCard) { // at TypeArgument(ex: List<? extends T>)
+ return super.visitWildcardType(wt, locale);
+ } else { // at TopLevelType(ex: ? extends List<T>, ? extends Number[][])
+ Type extendsBound = wt.getExtendsBound();
+ return extendsBound == null
+ ? OBJECT
+ : visit(extendsBound, locale);
}
}
@Override
public String visitType(Type t, Locale locale) {
String s = (t.tsym == null || t.tsym.name == null)
- ? "Object" // none
+ ? OBJECT // none
: t.tsym.name.toString();
return s;
}
+ @Override
+ public String visitClassType(ClassType ct, Locale locale) {
+ boolean prevUseWildCard = useWildCard;
+ try {
+ useWildCard = true;
+ return super.visitClassType(ct, locale);
+ } finally {
+ useWildCard = prevUseWildCard;
+ }
+ }
+
/**
* Converts a class name into a (possibly localized) string. Anonymous
* inner classes get converted into a localized string.
@@ -101,7 +120,7 @@
}
return s.toString();
***/
- return "Object";
+ return OBJECT;
} else if (sym.name.length() == 0) {
// Anonymous
String s;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java Wed Jan 06 14:54:24 2016 +0000
@@ -225,7 +225,7 @@
return false;
}
- void setStatus() {
+ void setStatus(AnalyzeTask at) {
if (!compilationDiagnostics.hasErrors()) {
status = VALID;
} else if (isRecoverable()) {
@@ -237,7 +237,7 @@
} else {
status = REJECTED;
}
- checkForOverwrite();
+ checkForOverwrite(at);
state.debug(DBG_GEN, "setStatus() %s - status: %s\n",
si, status);
@@ -361,17 +361,18 @@
si, status, unresolved);
}
- private void checkForOverwrite() {
+ private void checkForOverwrite(AnalyzeTask at) {
secondaryEvents = new ArrayList<>();
if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent);
// Defined methods can overwrite methods of other (equivalent) snippets
if (si.kind() == Kind.METHOD && status.isDefined) {
- String oqpt = ((MethodSnippet) si).qualifiedParameterTypes();
- String nqpt = computeQualifiedParameterTypes(si);
+ MethodSnippet msi = (MethodSnippet)si;
+ String oqpt = msi.qualifiedParameterTypes();
+ String nqpt = computeQualifiedParameterTypes(at, msi);
if (!nqpt.equals(oqpt)) {
- ((MethodSnippet) si).setQualifiedParamaterTypes(nqpt);
- Status overwrittenStatus = overwriteMatchingMethod(si);
+ msi.setQualifiedParamaterTypes(nqpt);
+ Status overwrittenStatus = overwriteMatchingMethod(msi);
if (overwrittenStatus != null) {
prevStatus = overwrittenStatus;
signatureChanged = true;
@@ -383,19 +384,19 @@
// Check if there is a method whose user-declared parameter types are
// different (and thus has a different snippet) but whose compiled parameter
// types are the same. if so, consider it an overwrite replacement.
- private Status overwriteMatchingMethod(Snippet si) {
- String qpt = ((MethodSnippet) si).qualifiedParameterTypes();
+ private Status overwriteMatchingMethod(MethodSnippet msi) {
+ String qpt = msi.qualifiedParameterTypes();
// Look through all methods for a method of the same name, with the
// same computed qualified parameter types
Status overwrittenStatus = null;
for (MethodSnippet sn : state.methods()) {
- if (sn != null && sn != si && sn.status().isActive && sn.name().equals(si.name())) {
+ if (sn != null && sn != msi && sn.status().isActive && sn.name().equals(msi.name())) {
if (qpt.equals(sn.qualifiedParameterTypes())) {
overwrittenStatus = sn.status();
SnippetEvent se = new SnippetEvent(
sn, overwrittenStatus, OVERWRITTEN,
- false, si, null, null);
+ false, msi, null, null);
sn.setOverwritten();
secondaryEvents.add(se);
state.debug(DBG_EVNT,
@@ -408,20 +409,16 @@
return overwrittenStatus;
}
- private String computeQualifiedParameterTypes(Snippet si) {
- MethodSnippet msi = (MethodSnippet) si;
- String qpt;
- AnalyzeTask at = state.taskFactory.new AnalyzeTask(msi.outerWrap());
- String rawSig = new TreeDissector(at).typeOfMethod();
+ private String computeQualifiedParameterTypes(AnalyzeTask at, MethodSnippet msi) {
+ String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod();
String signature = expunge(rawSig);
int paren = signature.lastIndexOf(')');
- if (paren < 0) {
- // Uncompilable snippet, punt with user parameter types
- qpt = msi.parameterTypes();
- } else {
- qpt = signature.substring(0, paren + 1);
- }
- return qpt;
+
+ // Extract the parameter type string from the method signature,
+ // if method did not compile use the user-supplied parameter types
+ return paren >= 0
+ ? signature.substring(0, paren + 1)
+ : msi.parameterTypes();
}
SnippetEvent event(String value, Exception exception) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Util.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,4 @@
- /*
+/*
* Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -91,4 +91,14 @@
static <T> Stream<T> stream(Iterable<T> iterable) {
return StreamSupport.stream(iterable.spliterator(), false);
}
+
+ static class Pair<T, U> {
+ final T first;
+ final U second;
+
+ Pair(T first, U second) {
+ this.first = first;
+ this.second = second;
+ }
+ }
}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/VarSnippet.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/VarSnippet.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.Collection;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java Wed Jan 06 14:54:24 2016 +0000
@@ -22,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package jdk.jshell;
import java.util.ArrayList;
--- a/langtools/test/com/sun/javadoc/T6735320/SerialFieldTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/T6735320/SerialFieldTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.io.ObjectStreamField;
import java.io.Serializable;
--- a/langtools/test/com/sun/javadoc/testCmndLineClass/C5.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testCmndLineClass/C5.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
*This is a description for C5.
*/
--- a/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* Testing en\u00e7\u00f4ded string.
* In the encoded comment string, Unicode U+00E7 is "Latin small letter C with cedilla"
--- a/langtools/test/com/sun/javadoc/testJavaFX/pkg1/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testJavaFX/pkg1/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
public class C {
--- a/langtools/test/com/sun/javadoc/testJavaFX/pkg1/D.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testJavaFX/pkg1/D.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
public class D extends C {}
--- a/langtools/test/com/sun/javadoc/testJavaFX/pkg2/Test.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testJavaFX/pkg2/Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg2;
import java.util.List;
--- a/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* This is an {@underline underline}.
* @todo Finish this class.
--- a/langtools/test/com/sun/javadoc/testOrdering/pkg1/A.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/A.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
import java.util.Collection;
import java.util.List;
--- a/langtools/test/com/sun/javadoc/testOrdering/pkg1/B.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/pkg1/B.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
public class B {
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/a/A.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/a/A.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package a;
/**
* A class
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/a/something.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/a/something.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package a;
/**
* A class
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/b/B.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/b/B.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package b;
/**
* Another class
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/b/something.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/b/something.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package b;
/**
* an annotation
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/e/something.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/e/something.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package e;
/**
* An enum
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/something/J.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/something/J.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package something;
public class J {
/**
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/something/package-info.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/something/package-info.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
/**
* A package
*/
--- a/langtools/test/com/sun/javadoc/testOrdering/src-2/something/something.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testOrdering/src-2/something/something.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package something;
/**
* An interface
--- a/langtools/test/com/sun/javadoc/testSearch/pkgfx/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testSearch/pkgfx/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkgfx;
public class C {
--- a/langtools/test/com/sun/javadoc/testSinceTag/pkg1/C1.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testSinceTag/pkg1/C1.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
import java.io.IOException;
--- a/langtools/test/com/sun/javadoc/testThrowsInheritence/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testThrowsInheritence/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
public class C implements I {
/**
--- a/langtools/test/com/sun/javadoc/testThrowsInheritence/I.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testThrowsInheritence/I.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
public interface I {
/**
* @throws java.lang.NullPointerException Test 1 fails
--- a/langtools/test/com/sun/javadoc/testTypeAnnotations/typeannos/Varargs.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testTypeAnnotations/typeannos/Varargs.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package typeannos;
import java.lang.annotation.*;
--- a/langtools/test/com/sun/javadoc/testUseOption/pkg1/AnAbstract.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/com/sun/javadoc/testUseOption/pkg1/AnAbstract.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,5 +20,6 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg1;
public abstract class AnAbstract implements UsedInterface {}
--- a/langtools/test/jdk/jshell/ClassesTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/jdk/jshell/ClassesTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8145239
* @summary Tests for EvaluationState.classes
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng ClassesTest
@@ -174,6 +175,27 @@
assertActiveKeys();
}
+ public void classesRedeclaration3() {
+ Snippet a = classKey(assertEval("class A { }"));
+ assertClasses(clazz(KullaTesting.ClassType.CLASS, "A"));
+ assertActiveKeys();
+
+ Snippet test1 = methodKey(assertEval("A test() { return null; }"));
+ Snippet test2 = methodKey(assertEval("void test(A a) { }"));
+ Snippet test3 = methodKey(assertEval("void test(int n) {A a;}"));
+ assertActiveKeys();
+
+ assertEval("interface A { }",
+ ste(MAIN_SNIPPET, VALID, VALID, true, null),
+ ste(test1, VALID, VALID, true, MAIN_SNIPPET),
+ ste(test2, VALID, VALID, true, MAIN_SNIPPET),
+ ste(test3, VALID, VALID, false, MAIN_SNIPPET),
+ ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+ assertClasses(clazz(KullaTesting.ClassType.INTERFACE, "A"));
+ assertMethods(method("()A", "test"), method("(A)void", "test"), method("(int)void", "test"));
+ assertActiveKeys();
+ }
+
public void classesCyclic1() {
Snippet b = classKey(assertEval("class B extends A { }",
added(RECOVERABLE_NOT_DEFINED)));
--- a/langtools/test/jdk/jshell/TypeNameTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/jdk/jshell/TypeNameTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,7 +23,8 @@
/*
* @test
- * @summary null test
+ * @bug 8144903
+ * @summary Tests for determining the type from the expression
* @build KullaTesting TestingInputStream
* @run testng TypeNameTest
*/
@@ -34,7 +35,6 @@
import static jdk.jshell.Snippet.Status.VALID;
import static org.testng.Assert.assertEquals;
-import static jdk.jshell.Snippet.Status.OVERWRITTEN;
@Test
public class TypeNameTest extends KullaTesting {
@@ -62,6 +62,11 @@
assertEquals(sn.typeName(), "Class<? extends String>");
}
+ public void testArrayTypeOfCapturedTypeName() {
+ VarSnippet sn = (VarSnippet) varKey(assertEval("\"\".getClass().getEnumConstants();"));
+ assertEquals(sn.typeName(), "String[]");
+ }
+
public void testJavaLang() {
VarSnippet sn = (VarSnippet) varKey(assertEval("\"\";"));
assertEquals(sn.typeName(), "String");
@@ -83,14 +88,16 @@
VarSnippet sn3 = (VarSnippet) varKey(assertEval("list3.iterator().next()"));
assertEquals(sn3.typeName(), "Object");
assertEval("class Test1<X extends CharSequence> { public X get() { return null; } }");
- Snippet x = varKey(assertEval("Test1<?> x = new Test1<>();"));
- VarSnippet sn4 = (VarSnippet) varKey(assertEval("x.get()"));
- assertEquals(sn4.typeName(), "CharSequence");
- assertEval("class Foo<X extends Number & CharSequence> { public X get() { return null; } }");
- assertEval("Foo<?> x = new Foo<>();",
- ste(MAIN_SNIPPET, VALID, VALID, true, null),
- ste(x, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
- VarSnippet sn5 = (VarSnippet) varKey(assertEval("x.get()"));
+ Snippet x = varKey(assertEval("Test1<?> test1 = new Test1<>();"));
+ VarSnippet sn4 = (VarSnippet) varKey(assertEval("test1.get()"));
+ assertEquals(sn4.typeName(), "Object");
+ assertEval("class Test2<X extends Number & CharSequence> { public X get() { return null; } }");
+ assertEval("Test2<?> test2 = new Test2<>();");
+ VarSnippet sn5 = (VarSnippet) varKey(assertEval("test2.get()"));
assertEquals(sn5.typeName(), "Object");
+ assertEval("class Test3<T> { T[][] get() { return null; } }", added(VALID));
+ assertEval("Test3<? extends String> test3 = new Test3<>();");
+ VarSnippet sn6 = (VarSnippet) varKey(assertEval("test3.get()"));
+ assertEquals(sn6.typeName(), "String[][]");
}
}
--- a/langtools/test/jdk/jshell/VariablesTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/jdk/jshell/VariablesTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -23,6 +23,7 @@
/*
* @test
+ * @bug 8144903
* @summary Tests for EvaluationState.variables
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng VariablesTest
@@ -184,6 +185,16 @@
assertActiveKeys();
}
+ public void variablesTemporaryArrayOfCapturedType() {
+ assertEval("class Test<T> { T[][] get() { return null; } }", added(VALID));
+ assertEval("Test<? extends String> test() { return new Test<>(); }", added(VALID));
+ assertEval("test().get()", added(VALID));
+ assertVariables(variable("String[][]", "$1"));
+ assertEval("\"\".getClass().getEnumConstants()", added(VALID));
+ assertVariables(variable("String[][]", "$1"), variable("String[]", "$2"));
+ assertActiveKeys();
+ }
+
public void variablesClassReplace() {
assertEval("import java.util.*;", added(VALID));
Snippet var = varKey(assertEval("List<Integer> list = new ArrayList<>();", "[]",
--- a/langtools/test/lib/combo/tools/javac/combo/Diagnostics.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/lib/combo/tools/javac/combo/Diagnostics.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package tools.javac.combo;
import javax.tools.Diagnostic;
--- a/langtools/test/lib/combo/tools/javac/combo/JavacTemplateTestBase.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/lib/combo/tools/javac/combo/JavacTemplateTestBase.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package tools.javac.combo;
import java.io.File;
--- a/langtools/test/lib/combo/tools/javac/combo/Template.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/lib/combo/tools/javac/combo/Template.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package tools.javac.combo;
import java.util.Map;
--- a/langtools/test/lib/combo/tools/javac/combo/TemplateTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/lib/combo/tools/javac/combo/TemplateTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -19,8 +19,8 @@
* 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 tools.javac.combo;
import org.testng.annotations.BeforeTest;
--- a/langtools/test/tools/doclint/tidy/util/Main.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/doclint/tidy/util/Main.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
package tidystats;
import java.io.IOException;
--- a/langtools/test/tools/javac/6199662/TreeInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6199662/TreeInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
package p;
import p.Tree.*;
--- a/langtools/test/tools/javac/6199662/TreeScanner.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6199662/TreeScanner.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
package p;
import p.Tree.*;
--- a/langtools/test/tools/javac/6302184/T6302184.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6302184/T6302184.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* This is a test that uses ISO 8859 encoding.
*/
--- a/langtools/test/tools/javac/6400872/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6400872/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,8 +21,6 @@
* questions.
*/
-
-
class C {
A a = new A();
B b = new B();
--- a/langtools/test/tools/javac/6508981/p/A.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6508981/p/A.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,5 +20,6 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package p;
class A { }
--- a/langtools/test/tools/javac/6547131/T.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6547131/T.java Wed Jan 06 14:54:24 2016 +0000
@@ -2,7 +2,7 @@
* @test
* @bug 6547131
* @summary java.lang.ClassFormatError when using old collection API
- * @compile T.java
+ * @compile p/Outer.jasm p/Outer$I.jasm T.java
* @run main T
*/
Binary file langtools/test/tools/javac/6547131/p/Outer$I.class has changed
Binary file langtools/test/tools/javac/6547131/p/Outer.class has changed
--- a/langtools/test/tools/javac/6917288/GraphicalInstallerTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/6917288/GraphicalInstallerTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/* @test
* @bug 6917288
* @summary Unnamed nested class is not generated
--- a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedA.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedA.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg;
public class ClassToBeStaticallyImportedA {
--- a/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/7153958/pkg/ClassToBeStaticallyImportedB.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg;
public class ClassToBeStaticallyImportedB {
Binary file langtools/test/tools/javac/InnerClassesAttribute/Outside$1$Inside.class has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/InnerClassesAttribute/Outside$1$Inside.jasm Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+super class Outside$1$Inside
+ version 45:3
+{
+
+Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+private InnerClass Inside=class Outside$1$Inside;
+
+}
\ No newline at end of file
Binary file langtools/test/tools/javac/InnerClassesAttribute/Outside.class has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/InnerClassesAttribute/Outside.jasm Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+super public class Outside
+ version 45:3
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+Method method:"()V"
+ stack 0 locals 1
+{
+ return;
+}
+
+private InnerClass Inside=class Outside$1$Inside;
+
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/InnerClassesAttribute/Test.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/InnerClassesAttribute/Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,7 +27,7 @@
* @summary The compiler used to crash when it saw a correctly-formed
* InnerClasses attribute in a .class file.
* @author turnidge
- *
+ * @build Outside Outside$1$Inside
* @compile Test.java
*/
public
--- a/langtools/test/tools/javac/MethodParameters/ClassFileVisitor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/MethodParameters/ClassFileVisitor.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -279,7 +279,7 @@
userParam = param;
}
}
- if (expect != null && !param.equals(expect)) {
+ if (check > 0 && expect != null && !param.equals(expect)) {
error(prefix + "param[" + x + "]='"
+ param + "' expected '" + expect + "'");
return null;
@@ -346,6 +346,17 @@
}
}
}
+
+ if (synthetic && !mandated && !allowSynthetic) {
+ //patch treatment for local captures
+ if (isAnon || (isInner & !isStatic)) {
+ expect = "val\\$.*";
+ allowSynthetic = true;
+ if (isFinal) {
+ expect = "final val\\$.*";
+ }
+ }
+ }
} else if (isEnum && mNumParams == 1 && index == 0 && mName.equals("valueOf")) {
expect = "name";
allowMandated = true;
@@ -411,7 +422,6 @@
if (mSynthetic) {
return 0;
}
-
// Otherwise, do check test parameter naming convention.
return 1;
}
--- a/langtools/test/tools/javac/MethodParameters/LocalClassTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/MethodParameters/LocalClassTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -45,6 +45,16 @@
}
new LocalClassTest().foo();
}
+
+ void test(final int i) {
+ class CapturingLocal {
+ CapturingLocal(final int j) {
+ this(new Object() { void test() { int x = i; } });
+ }
+ CapturingLocal(Object o) { }
+ }
+ new CapturingLocal(i) { };
+ }
}
--- a/langtools/test/tools/javac/MethodParameters/LocalClassTest.out Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/MethodParameters/LocalClassTest.out Wed Jan 06 14:54:24 2016 +0000
@@ -1,12 +1,21 @@
-class LocalClassTest$1Local_has_constructor -- inner
-LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/, a, ba)
-LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/)
-LocalClassTest$1Local_has_constructor.foo(m, nm)
-LocalClassTest$1Local_has_constructor.foo()
+class LocalClassTest$1 -- anon
+LocalClassTest$1.<init>(final this$0/*implicit*/, final j, final val$i/*synthetic*/)
+class LocalClassTest$1CapturingLocal$1 -- anon
+LocalClassTest$1CapturingLocal$1.<init>(final val$this$0/*synthetic*/, final val$val$i/*synthetic*/)
+LocalClassTest$1CapturingLocal$1.test()
+class LocalClassTest$1CapturingLocal -- inner
+LocalClassTest$1CapturingLocal.<init>(final this$0/*implicit*/, final j, final val$i/*synthetic*/)
+LocalClassTest$1CapturingLocal.<init>(final this$0/*implicit*/, o, final val$i/*synthetic*/)
class LocalClassTest$1Local_default_constructor -- inner
LocalClassTest$1Local_default_constructor.<init>(final this$0/*implicit*/)
LocalClassTest$1Local_default_constructor.foo()
LocalClassTest$1Local_default_constructor.foo(m, nm)
+class LocalClassTest$1Local_has_constructor -- inner
+LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/)
+LocalClassTest$1Local_has_constructor.<init>(final this$0/*implicit*/, a, ba)
+LocalClassTest$1Local_has_constructor.foo()
+LocalClassTest$1Local_has_constructor.foo(m, nm)
class LocalClassTest --
LocalClassTest.<init>()
-LocalClassTest.foo()
\ No newline at end of file
+LocalClassTest.foo()
+LocalClassTest.test(final i)
--- a/langtools/test/tools/javac/MethodParameters/ReflectionVisitor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/MethodParameters/ReflectionVisitor.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -164,6 +164,17 @@
}
}
+ if (p.isSynthetic() && !p.isImplicit() && !allowSynthetic) {
+ //patch treatment for local captures
+ if (isAnon || ((isLocal || isAnon) & !isStatic)) {
+ expect = "val\\$.*";
+ allowSynthetic = true;
+ if (isFinal) {
+ expect = "final val\\$.*";
+ }
+ }
+ }
+
// Check expected flags
if (p.isSynthetic() && p.isImplicit()) {
error(prefix + "param[" + i + "]='" + pname +
--- a/langtools/test/tools/javac/NameClash/NameClashTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/NameClash/NameClashTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * 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
Binary file langtools/test/tools/javac/T6435291/T.class has changed
--- a/langtools/test/tools/javac/T6435291/T6435291.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/T6435291/T6435291.java Wed Jan 06 14:54:24 2016 +0000
@@ -30,6 +30,7 @@
* jdk.compiler/com.sun.tools.javac.code
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.util
+ * @build T
* @run main/othervm T6435291
*/
--- a/langtools/test/tools/javac/T6458823/MyProcessor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/T6458823/MyProcessor.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,25 +1,25 @@
- /*
- * Copyright (c) 2010, 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.
- */
+/*
+ * Copyright (c) 2010, 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.Set;
import javax.annotation.processing.*;
--- a/langtools/test/tools/javac/T6942649.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/T6942649.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 6942649
--- a/langtools/test/tools/javac/annotations/neg/8022765/VerifyAnnotationsAttributed.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/neg/8022765/VerifyAnnotationsAttributed.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.MemberSelectTree;
--- a/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/TargetTypes.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
--- a/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/TypeProcOnly.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.io.*;
import java.util.Set;
import java.util.HashSet;
--- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/T8008769.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/T8008769.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
/*
* @test
* @summary Repeated type-annotations on type parm of local variable
--- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/PackageProcessor.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.util.HashSet;
import java.util.Set;
--- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/Anno.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package mypackage;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Retention;
--- a/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/packageanno/mypackage/MyClass.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package mypackage;
public class MyClass {}
--- a/langtools/test/tools/javac/api/6557752/T6557752.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/api/6557752/T6557752.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 6557752
--- a/langtools/test/tools/javac/api/TestGetElementReferenceData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/api/TestGetElementReferenceData.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package test;
/*getElement:PACKAGE:test*/
import java.lang.annotation.*;
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerClassesTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 8034854 8042251
--- a/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/classfiles/attributes/innerclasses/InnerEnumInInnerAnnotationTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 8042251
--- a/langtools/test/tools/javac/defaultMethods/Assertions.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/defaultMethods/Assertions.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package test;
import java.util.Arrays;
--- a/langtools/test/tools/javac/defaultMethods/crossCompile/Clinit.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/defaultMethods/crossCompile/Clinit.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
interface Clinit {
String s = Inner.m();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,18 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8145466
+ * @summary javac: No line numbers in compilation error
+ * @compile/fail/ref=DiagnosticRewriterTest.out -Xdiags:compact -XDrawDiagnostics DiagnosticRewriterTest.java
+ */
+
+class DiagnosticRewriterTest {
+ void test() {
+ new Object() {
+ void g() {
+ m(2L);
+ }
+ };
+ }
+
+ void m(int i) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest.out Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,3 @@
+DiagnosticRewriterTest.java:12:15: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: long, int)
+- compiler.note.compressed.diags
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest2.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,22 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8145466
+ * @summary javac: No line numbers in compilation error
+ * @compile/fail/ref=DiagnosticRewriterTest2.out -Xdiags:compact -XDrawDiagnostics DiagnosticRewriterTest2.java
+ */
+
+class DiagnosticRewriterTest2 {
+ class Bar {
+ Bar(Object o) { }
+ }
+ void test() {
+ new Bar(null) {
+ void g() {
+ m(2L);
+ m();
+ }
+ };
+ }
+
+ void m(int i) { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/DiagnosticRewriterTest2.out Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,4 @@
+DiagnosticRewriterTest2.java:15:15: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: long, int)
+DiagnosticRewriterTest2.java:16:13: compiler.err.cant.apply.symbol: kindname.method, m, int, compiler.misc.no.args, kindname.class, DiagnosticRewriterTest2, (compiler.misc.arg.length.mismatch)
+- compiler.note.compressed.diags
+2 errors
--- a/langtools/test/tools/javac/diags/HTMLWriter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/diags/HTMLWriter.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996,2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2010, 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
@@ -21,8 +21,6 @@
* questions.
*/
-
-
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
--- a/langtools/test/tools/javac/diags/examples/DiamondAndAnonClass.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/diags/examples/DiamondAndAnonClass.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
--- a/langtools/test/tools/javac/diags/examples/DiamondAndNonDenotableTypes.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/diags/examples/DiamondAndNonDenotableTypes.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/langtools/test/tools/javac/doctree/positions/TestPositionSource.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/doctree/positions/TestPositionSource.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
public class TestPositionSource {
/**First sentence.
--- a/langtools/test/tools/javac/file/zip/8003512/LoadClassFromJava6CreatedJarTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/file/zip/8003512/LoadClassFromJava6CreatedJarTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,3 @@
-
/*
* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -22,6 +21,7 @@
* questions.
*/
+
/*
* @test
* @bug 8003512
--- a/langtools/test/tools/javac/flow/AliveRanges.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/flow/AliveRanges.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.*;
@Repeatable(AliveRanges.class)
--- a/langtools/test/tools/javac/generics/8004094/B.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/8004094/B.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
abstract class A {
private static String s = null;
--- a/langtools/test/tools/javac/generics/bridges/Bridge.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/Bridge.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.Repeatable;
@Repeatable(Bridges.class)
--- a/langtools/test/tools/javac/generics/bridges/Bridges.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/Bridges.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
@interface Bridges {
Bridge[] value();
}
--- a/langtools/test/tools/javac/generics/bridges/tests/TestBridgeWithDefault.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestBridgeWithDefault.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestBridgeWithDefault {
interface A { Object m(int x); }
--- a/langtools/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical01.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical01.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestClassAndInterfaceBridgeIdentical01 {
interface A { Object m(); }
--- a/langtools/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical02.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestClassAndInterfaceBridgeIdentical02.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestClassAndInterfaceBridgeIdentical02 {
interface A<X extends Object> { void m(X x); }
--- a/langtools/test/tools/javac/generics/bridges/tests/TestNoBridgeInSiblingsSuper.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestNoBridgeInSiblingsSuper.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestNoBridgeInSiblingSuper {
interface A { Object m(); }
interface B { String m(); }
--- a/langtools/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges01.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges01.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestNoDuplicateBridges01 {
interface A1 { Object m(); }
interface A2 { Object m(); }
--- a/langtools/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges02.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/bridges/tests/TestNoDuplicateBridges02.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class TestNoDuplicateBridges02 {
interface A<T> {
A<T> get();
--- a/langtools/test/tools/javac/generics/diamond/pos/NestedDiamondAllocationTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/generics/diamond/pos/NestedDiamondAllocationTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/CaptureInDeclaredBound.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 7190296 8033718
+ * @summary F-bounded capture variable is within its declared bound
+ * @compile CaptureInDeclaredBound.java
+ */
+
+public class CaptureInDeclaredBound {
+
+ class C<T> {}
+
+ interface I<X extends Comparable<X>> {
+ C<X> get();
+ }
+
+ <Z extends Comparable<? super Z>> void m(C<Z> arg) {}
+
+ void test(I<?> arg) {
+ m(arg.get());
+ }
+
+}
--- a/langtools/test/tools/javac/implicitCompile/Implicit.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/implicitCompile/Implicit.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,5 +20,6 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
class Implicit {
}
--- a/langtools/test/tools/javac/importscope/TestDuplicateImport.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/importscope/TestDuplicateImport.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
--- a/langtools/test/tools/javac/importscope/TestLazyImportScope.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/importscope/TestLazyImportScope.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
--- a/langtools/test/tools/javac/lambda/8068399/T8068399.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/8068399/T8068399.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
/*
* @test
* @bug 8068399 8069545
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lambda/8142876/T8142876.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8142876
+ * @summary Javac does not correctly implement wildcards removal from functional interfaces
+ * @compile T8142876.java
+ */
+class T8142876 {
+ interface I<R extends Runnable, T> {
+ void m();
+ }
+
+ void test() {
+ I<? extends O, String> succeed = this::ff;
+ I<? extends Comparable<String>, String> failed = this::ff;
+ }
+
+ interface O {}
+
+ private void ff(){}
+}
--- a/langtools/test/tools/javac/lambda/LocalBreakAndContinue.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/LocalBreakAndContinue.java Wed Jan 06 14:54:24 2016 +0000
@@ -19,7 +19,6 @@
* 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.
-
*/
/*
--- a/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodTestCase.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodTestCase.java Wed Jan 06 14:54:24 2016 +0000
@@ -19,8 +19,8 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
- *
*/
+
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
--- a/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -19,8 +19,8 @@
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
- *
*/
+
import java.io.IOException;
import org.testng.annotations.Test;
--- a/langtools/test/tools/javac/lambda/inaccessibleMref01/p1/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/inaccessibleMref01/p1/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package p1;
public class C {
--- a/langtools/test/tools/javac/lambda/inaccessibleMref02/p1/C.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/inaccessibleMref02/p1/C.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package p1;
class Sup {
--- a/langtools/test/tools/javac/lambda/methodReferenceExecution/pkg/B.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/methodReferenceExecution/pkg/B.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg;
class A {
public static void m() {
--- a/langtools/test/tools/javac/lambda/separate/Foo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/lambda/separate/Foo.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
interface Foo<X extends Number> {
void m(X x);
}
--- a/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/missingSuperRecovery/MissingSuperRecovery.java Wed Jan 06 14:54:24 2016 +0000
@@ -4,7 +4,7 @@
* @summary Check for proper error recovery when superclass of extended
* class is no longer available during a subsequent compilation.
* @author maddox
- *
+ * @build impl
* @compile/fail/ref=MissingSuperRecovery.out -XDdiags=%b:%l:%_%m MissingSuperRecovery.java
*/
Binary file langtools/test/tools/javac/missingSuperRecovery/impl.class has changed
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/missingSuperRecovery/impl.jasm Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+super public class impl
+ implements base
+ version 45:3
+{
+
+public Method "<init>":"()V"
+ stack 1 locals 1
+{
+ aload_0;
+ invokespecial Method java/lang/Object."<init>":"()V";
+ return;
+}
+
+public Method run:"()V"
+ stack 0 locals 1
+{
+ return;
+}
+
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/options/T7022337.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/options/T7022337.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 7022337
--- a/langtools/test/tools/javac/policy/test3/Test.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/policy/test3/Test.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/* @test
* @bug 6813059
* @summary
--- a/langtools/test/tools/javac/processing/6414633/A.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/processing/6414633/A.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
import java.util.*;
import javax.annotation.*;
import javax.annotation.processing.*;
--- a/langtools/test/tools/javac/processing/TestWarnErrorCount.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/processing/TestWarnErrorCount.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 7022337
--- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 6639645 7026414 7025809
--- a/langtools/test/tools/javac/proprietary/WarnVariable.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/proprietary/WarnVariable.java Wed Jan 06 14:54:24 2016 +0000
@@ -3,7 +3,7 @@
* @bug 6380059
* @summary Emit warnings for proprietary packages in the boot class path
* @author Peter von der Ah\u00e9
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
* @compile WarnVariable.java
* @compile/fail/ref=WarnVariable.out -XDrawDiagnostics -Werror WarnVariable.java
* @compile/fail/ref=WarnVariable.out -XDrawDiagnostics -Werror -nowarn WarnVariable.java
@@ -12,6 +12,6 @@
public class WarnVariable {
public static void main(String... args) {
- System.out.println(sun.misc.FloatConsts.POSITIVE_INFINITY);
+ System.out.println(sun.security.x509.X509CertImpl.NAME);
}
}
--- a/langtools/test/tools/javac/proprietary/WarnVariable.out Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/proprietary/WarnVariable.out Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,4 @@
-WarnVariable.java:15:36: compiler.warn.sun.proprietary: sun.misc.FloatConsts
+WarnVariable.java:15:45: compiler.warn.sun.proprietary: sun.security.x509.X509CertImpl
- compiler.err.warnings.and.werror
1 error
1 warning
--- a/langtools/test/tools/javac/proprietary/WarnWildcard.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/proprietary/WarnWildcard.java Wed Jan 06 14:54:24 2016 +0000
@@ -3,7 +3,7 @@
* @bug 6380059
* @summary Emit warnings for proprietary packages in the boot class path
* @author Peter von der Ah\u00e9
- * @modules java.base/sun.misc
+ * @modules java.base/sun.security.x509
* @compile WarnWildcard.java
* @compile/fail/ref=WarnWildcard.out -XDrawDiagnostics -Werror WarnWildcard.java
* @compile/fail/ref=WarnWildcard.out -XDrawDiagnostics -Werror -nowarn WarnWildcard.java
@@ -11,5 +11,5 @@
*/
public class WarnWildcard {
- java.util.Collection<? extends sun.misc.FloatConsts> x;
+ java.util.Collection<? extends sun.security.x509.X509CertImpl> x;
}
--- a/langtools/test/tools/javac/proprietary/WarnWildcard.out Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/proprietary/WarnWildcard.out Wed Jan 06 14:54:24 2016 +0000
@@ -1,4 +1,4 @@
-WarnWildcard.java:14:44: compiler.warn.sun.proprietary: sun.misc.FloatConsts
+WarnWildcard.java:14:53: compiler.warn.sun.proprietary: sun.security.x509.X509CertImpl
- compiler.err.warnings.and.werror
1 error
1 warning
--- a/langtools/test/tools/javac/resolve/Candidate.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/resolve/Candidate.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
--- a/langtools/test/tools/javac/resolve/Pos.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/resolve/Pos.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
--- a/langtools/test/tools/javac/resolve/TraceResolve.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/resolve/TraceResolve.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
--- a/langtools/test/tools/javac/resolve/tests/AbstractMerge.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/resolve/tests/AbstractMerge.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
@TraceResolve
class AbstractMerge {
--- a/langtools/test/tools/javac/scope/DupUnsharedTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/scope/DupUnsharedTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
--- a/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/scope/RemoveSymbolUnitTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * 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
--- a/langtools/test/tools/javac/staticImport/6665223/pkg/A.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/staticImport/6665223/pkg/A.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg;
import static pkg.B.b;
--- a/langtools/test/tools/javac/staticImport/6665223/pkg/B.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/staticImport/6665223/pkg/B.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package pkg;
class B extends B2 {}
--- a/langtools/test/tools/javac/tree/JavacTreeScannerTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/tree/JavacTreeScannerTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* Utility and test program to check javac's internal TreeScanner class.
* The program can be run standalone, or as a jtreg test. For info on
--- a/langtools/test/tools/javac/tree/SourceTreeScannerTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/tree/SourceTreeScannerTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* Utility and test program to check javac's internal TreeScanner class.
* The program can be run standalone, or as a jtreg test. For info on
--- a/langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/tree/TestAnnotatedAnonClass.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* This file is not a regular test, but is processed by ./TreePosTest.java,
* which verifies the position info in the javac tree.
--- a/langtools/test/tools/javac/types/CastTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/types/CastTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -35,8 +35,6 @@
*/
import com.sun.tools.javac.code.Type;
-import com.sun.tools.javac.code.Type.*;
-import com.sun.tools.javac.code.Symbol.*;
import java.lang.reflect.Array;
import static com.sun.tools.javac.code.Flags.*;
@@ -65,7 +63,7 @@
/*C*/ { F , F , F , F , F , F , F , F , T, F , T, T, F , F , F , F , F , F , F , F , F , F , F , F },
/*+C*/ { F , F , F , F , F , F , F , F , F, T , F, T, F , F , F , F , F , F , F , F , F , F , F , F },
/*I*/ { F , F , F , F , F , F , F , F , T, F , T, T, F , F , F , F , F , F , F , F , F , F , F , F },
- /*T*/ { F , F , F , F , F , F , F , F , T, T , T, T, T , T , T , T , T , T , T , T , T , T , T , T },
+ /*T*/ { T , T , T , T , T , T , T , T , T, T , T, T, T , T , T , T , T , T , T , T , T , T , T , T },
/*byte[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, T , F , F , F , F , F , F , F , F , F , F , F },
/*short[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , T , F , F , F , F , F , F , F , F , F , F },
/*int[]*/ { F , F , F , F , F , F , F , F , F, F , F, T, F , F , T , F , F , F , F , F , F , F , F , F },
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/CastToTypeVarTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8144832
+ * @summary cast conversion fails when converting a type-variable to primitive type
+ * @compile -Werror -Xlint:all CastToTypeVarTest.java
+ */
+
+public class CastToTypeVarTest<X, Y extends X> {
+ void foo(Y y) {
+ X x = (X)y;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/types/CastTypeVarToPrimitiveTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8144832
+ * @summary cast conversion fails when converting a type-variable to primitive type
+ * @compile CastTypeVarToPrimitiveTest.java
+ */
+
+public class CastTypeVarToPrimitiveTest<T> {
+ void foo(T valIn){
+ double val = (double)valIn;
+ }
+}
--- a/langtools/test/tools/javac/warnings/suppress/T8021112a.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javac/warnings/suppress/T8021112a.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package test;
/**
--- a/langtools/test/tools/javadoc/parser/7091528/p/C3.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javadoc/parser/7091528/p/C3.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/** This is class C3, and no package for me please */
public class C3 {}
--- a/langtools/test/tools/javadoc/subpackageIgnore/pkg1/not-subpkg/SomeJavaFile.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javadoc/subpackageIgnore/pkg1/not-subpkg/SomeJavaFile.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,3 +20,4 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
--- a/langtools/test/tools/javap/ExtPath.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javap/ExtPath.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/**
* @test
* @bug 6428896
--- a/langtools/test/tools/javap/T4880672.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javap/T4880672.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 4880672 7031005
--- a/langtools/test/tools/javap/T6729471.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javap/T6729471.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 6729471
--- a/langtools/test/tools/javap/T6866657.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/javap/T6866657.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 6866657
--- a/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/JdepsDependencyClosure.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseUnsafe2.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/DontUseUnsafe2.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.indirect;
import use.unsafe.*;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseUnsafeIndirectly.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect/UseUnsafeIndirectly.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.indirect;
import use.unsafe.UseClassWithUnsafe;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseUnsafe3.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/DontUseUnsafe3.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.indirect2;
import use.unsafe.*;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseUnsafeIndirectly2.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/indirect2/UseUnsafeIndirectly2.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.indirect2;
import use.unsafe.UseUnsafeClass;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/DontUseUnsafe.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/DontUseUnsafe.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.unsafe;
public class DontUseUnsafe {
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.unsafe;
import sun.misc.Unsafe;
--- a/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass2.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/jdeps/VerboseFormat/use/unsafe/UseUnsafeClass2.java Wed Jan 06 14:54:24 2016 +0000
@@ -20,6 +20,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
+
package use.unsafe;
import sun.misc.Unsafe;
--- a/langtools/test/tools/lib/ToolBox.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/lib/ToolBox.java Wed Jan 06 14:54:24 2016 +0000
@@ -124,9 +124,6 @@
/** The stream used for logging output. */
public PrintStream out = System.err;
- JavaCompiler compiler;
- StandardJavaFileManager standardJavaFileManager;
-
/**
* Checks if the host OS is some version of Windows.
* @return true if the host OS is some version of Windows
@@ -868,15 +865,18 @@
*/
public class JavacTask extends AbstractTask<JavacTask> {
private boolean includeStandardOptions;
- private String classpath;
- private String sourcepath;
- private String outdir;
+ private List<Path> classpath;
+ private List<Path> sourcepath;
+ private Path outdir;
private List<String> options;
private List<String> classes;
private List<String> files;
private List<JavaFileObject> fileObjects;
private JavaFileManager fileManager;
+ private JavaCompiler compiler;
+ private StandardJavaFileManager internalFileManager;
+
/**
* Creates a task to execute {@code javac} using API mode.
*/
@@ -898,7 +898,20 @@
* @return this task object
*/
public JavacTask classpath(String classpath) {
- this.classpath = classpath;
+ this.classpath = Stream.of(classpath.split(File.pathSeparator))
+ .filter(s -> !s.isEmpty())
+ .map(s -> Paths.get(s))
+ .collect(Collectors.toList());
+ return this;
+ }
+
+ /**
+ * Sets the classpath.
+ * @param classpath the classpath
+ * @return this task object
+ */
+ public JavacTask classpath(Path... classpath) {
+ this.classpath = Arrays.asList(classpath);
return this;
}
@@ -908,7 +921,20 @@
* @return this task object
*/
public JavacTask sourcepath(String sourcepath) {
- this.sourcepath = sourcepath;
+ this.sourcepath = Stream.of(sourcepath.split(File.pathSeparator))
+ .filter(s -> !s.isEmpty())
+ .map(s -> Paths.get(s))
+ .collect(Collectors.toList());
+ return this;
+ }
+
+ /**
+ * Sets the sourcepath.
+ * @param classpath the sourcepath
+ * @return this task object
+ */
+ public JavacTask sourcepath(Path... sourcepath) {
+ this.sourcepath = Arrays.asList(sourcepath);
return this;
}
@@ -918,6 +944,16 @@
* @return this task object
*/
public JavacTask outdir(String outdir) {
+ this.outdir = Paths.get(outdir);
+ return this;
+ }
+
+ /**
+ * Sets the output directory.
+ * @param outdir the output directory
+ * @return this task object
+ */
+ public JavacTask outdir(Path outdir) {
this.outdir = outdir;
return this;
}
@@ -1039,38 +1075,43 @@
}
private int runAPI(PrintWriter pw) throws IOException {
-// if (compiler == null) {
- // TODO: allow this to be set externally
-// compiler = ToolProvider.getSystemJavaCompiler();
- compiler = JavacTool.create();
-// }
+ try {
+// if (compiler == null) {
+ // TODO: allow this to be set externally
+// compiler = ToolProvider.getSystemJavaCompiler();
+ compiler = JavacTool.create();
+// }
- if (fileManager == null)
- fileManager = compiler.getStandardFileManager(null, null, null);
- if (outdir != null)
- setLocation(StandardLocation.CLASS_OUTPUT, toFiles(outdir));
- if (classpath != null)
- setLocation(StandardLocation.CLASS_PATH, toFiles(classpath));
- if (sourcepath != null)
- setLocation(StandardLocation.SOURCE_PATH, toFiles(sourcepath));
- List<String> allOpts = new ArrayList<>();
- if (options != null)
- allOpts.addAll(options);
+ if (fileManager == null)
+ fileManager = internalFileManager = compiler.getStandardFileManager(null, null, null);
+ if (outdir != null)
+ setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outdir));
+ if (classpath != null)
+ setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
+ if (sourcepath != null)
+ setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);
+ List<String> allOpts = new ArrayList<>();
+ if (options != null)
+ allOpts.addAll(options);
- Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
- JavaCompiler.CompilationTask task = compiler.getTask(pw,
- fileManager,
- null, // diagnostic listener; should optionally collect diags
- allOpts,
- classes,
- allFiles);
- return ((JavacTaskImpl) task).doCall().exitCode;
+ Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
+ JavaCompiler.CompilationTask task = compiler.getTask(pw,
+ fileManager,
+ null, // diagnostic listener; should optionally collect diags
+ allOpts,
+ classes,
+ allFiles);
+ return ((JavacTaskImpl) task).doCall().exitCode;
+ } finally {
+ if (internalFileManager != null)
+ internalFileManager.close();
+ }
}
- private void setLocation(StandardLocation location, List<File> files) throws IOException {
+ private void setLocationFromPaths(StandardLocation location, List<Path> files) throws IOException {
if (!(fileManager instanceof StandardJavaFileManager))
throw new IllegalStateException("not a StandardJavaFileManager");
- ((StandardJavaFileManager) fileManager).setLocation(location, files);
+ ((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
}
private int runCommand(PrintWriter pw) {
@@ -1105,15 +1146,15 @@
args.addAll(options);
if (outdir != null) {
args.add("-d");
- args.add(outdir);
+ args.add(outdir.toString());
}
if (classpath != null) {
args.add("-classpath");
- args.add(classpath);
+ args.add(toSearchPath(classpath));
}
if (sourcepath != null) {
args.add("-sourcepath");
- args.add(sourcepath);
+ args.add(toSearchPath(sourcepath));
}
if (classes != null)
args.addAll(classes);
@@ -1123,23 +1164,20 @@
return args;
}
- private List<File> toFiles(String path) {
- List<File> result = new ArrayList<>();
- for (String s : path.split(File.pathSeparator)) {
- if (!s.isEmpty())
- result.add(new File(s));
- }
- return result;
+ private String toSearchPath(List<Path> files) {
+ return files.stream()
+ .map(Path::toString)
+ .collect(Collectors.joining(File.pathSeparator));
}
private Iterable<? extends JavaFileObject> joinFiles(
List<String> files, List<JavaFileObject> fileObjects) {
if (files == null)
return fileObjects;
- if (standardJavaFileManager == null)
- standardJavaFileManager = compiler.getStandardFileManager(null, null, null);
+ if (internalFileManager == null)
+ internalFileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> filesAsFileObjects =
- standardJavaFileManager.getJavaFileObjectsFromStrings(files);
+ internalFileManager.getJavaFileObjectsFromStrings(files);
if (fileObjects == null)
return filesAsFileObjects;
List<JavaFileObject> combinedList = new ArrayList<>();
@@ -1364,6 +1402,15 @@
}
/**
+ * Creates a JarTask for use with a given jar file.
+ * @param path the file
+ */
+ public JarTask(Path path) {
+ this();
+ jar = path;
+ }
+
+ /**
* Sets a manifest for the jar file.
* @param manifest the manifest
* @return this task object
@@ -1417,6 +1464,16 @@
}
/**
+ * Sets the base directory for files to be written into the jar file.
+ * @param baseDir the base directory
+ * @return this task object
+ */
+ public JarTask baseDir(Path baseDir) {
+ this.baseDir = baseDir;
+ return this;
+ }
+
+ /**
* Sets the files to be written into the jar file.
* @param files the files
* @return this task object
--- a/langtools/test/tools/sjavac/ExclPattern.java Wed Jan 06 09:39:55 2016 -0500
+++ b/langtools/test/tools/sjavac/ExclPattern.java Wed Jan 06 14:54:24 2016 +0000
@@ -21,7 +21,6 @@
* questions.
*/
-
/*
* @test
* @bug 8037085
--- a/make/Help.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/Help.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -83,6 +83,7 @@
$(info $(_) # To see executed command lines, use LOG=debug)
$(info $(_) JOBS=<n> # Run <n> parallel make jobs)
$(info $(_) # Note that -jN does not work as expected!)
+ $(info $(_) TEST_JOBS=<n> # Run <n> parallel test jobs)
$(info $(_) CONF_CHECK=<method> # What to do if spec file is out of date)
$(info $(_) # method is 'auto', 'ignore' or 'fail' (default))
$(info $(_) make test TEST=<test> # Only run the given test or tests, e.g.)
--- a/make/InitSupport.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/InitSupport.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -40,7 +40,8 @@
##############################################################################
# Make control variables, handled by Init.gmk
- INIT_CONTROL_VARIABLES := LOG CONF CONF_NAME SPEC JOBS CONF_CHECK COMPARE_BUILD
+ INIT_CONTROL_VARIABLES := LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \
+ COMPARE_BUILD
# All known make control variables
MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER
--- a/make/MainSupport.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/MainSupport.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -35,7 +35,8 @@
($(CD) $(SRC_ROOT)/test && $(MAKE) $(MAKE_ARGS) -j1 -k MAKEFLAGS= \
JT_HOME=$(JT_HOME) PRODUCT_HOME=$(JDK_IMAGE_DIR) \
TEST_IMAGE_DIR=$(TEST_IMAGE_DIR) \
- ALT_OUTPUTDIR=$(OUTPUT_ROOT) CONCURRENCY=$(JOBS) $1) || true
+ ALT_OUTPUTDIR=$(OUTPUT_ROOT) TEST_JOBS=$(TEST_JOBS) \
+ JOBS=$(JOBS) $1) || true
endef
# Cleans the dir given as $1
--- a/make/common/MakeBase.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/common/MakeBase.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -151,16 +151,16 @@
$(eval compress_paths = \
$(strip $(shell $(CAT) $(SRC_ROOT)/make/common/support/ListPathsSafely-pre-compress.incl)))
compress_paths += \
-$(subst $(SRC_ROOT),X97,\
-$(subst $(OUTPUT_ROOT),X98,\
-$(subst X,X00,\
+ $(subst $(SRC_ROOT),X97, \
+ $(subst $(OUTPUT_ROOT),X98, \
+ $(subst X,X00, \
$(subst $(SPACE),\n,$(strip $1)))))
$(eval compress_paths += \
$(strip $(shell $(CAT) $(SRC_ROOT)/make/common/support/ListPathsSafely-post-compress.incl)))
decompress_paths=$(SED) -f $(SRC_ROOT)/make/common/support/ListPathsSafely-uncompress.sed \
-e 's|X99|\\n|g' \
- -e 's|X98|$(OUTPUT_ROOT)|g' -e 's|X97|$(SRC_ROOT)|g' \
+ -e 's|X98|$(OUTPUT_ROOT)|g' -e 's|X97|$(SRC_ROOT)|g' \
-e 's|X00|X|g'
ListPathsSafely_IfPrintf = \
@@ -172,10 +172,10 @@
# Param 1 - Name of variable containing paths/arguments to output
# Param 2 - File to print to
# Param 3 - Set to true to append to file instead of overwriting
-define ListPathsSafely
- ifneq (,$$(word 10001,$$($1)))
- $$(error Cannot list safely more than 10000 paths. $1 has $$(words $$($1)) paths!)
- endif
+ define ListPathsSafely
+ ifneq (,$$(word 10001,$$($1)))
+ $$(error Cannot list safely more than 10000 paths. $1 has $$(words $$($1)) paths!)
+ endif
$$(call MakeDir, $$(dir $2))
ifneq ($$(strip $3), true)
$$(shell $(RM) $$(strip $2))
@@ -230,7 +230,7 @@
$$(call ListPathsSafely_IfPrintf,$1,$2,9251,9500)
$$(call ListPathsSafely_IfPrintf,$1,$2,9501,9750)
$$(call ListPathsSafely_IfPrintf,$1,$2,9751,10000)
-endef
+ endef
endif # HAS_FILE_FUNCTION
# The source tips can come from the Mercurial repository, or in the files
@@ -285,18 +285,24 @@
# Never remove warning messages; this is just for completeness
LOG_WARN :=
ifneq ($$(findstring $$(LOG_LEVEL), info debug trace),)
+ LogInfo = $$(info $$(strip $$1))
LOG_INFO :=
else
+ LogInfo =
LOG_INFO := > /dev/null
endif
ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
+ LogDebug = $$(info $$(strip $$1))
LOG_DEBUG :=
else
+ LogDebug =
LOG_DEBUG := > /dev/null
endif
ifneq ($$(findstring $$(LOG_LEVEL), trace),)
+ LogTrace = $$(info $$(strip $$1))
LOG_TRACE :=
else
+ LogTrace =
LOG_TRACE := > /dev/null
endif
endef
@@ -450,6 +456,23 @@
$(strip $(if $1,$(patsubst $(firstword $1)%,%,\
$(call remove-prefixes,$(filter-out $(firstword $1),$1),$2)),$2))
+# Convert the string given to upper case, without any $(shell)
+# Inspired by http://lists.gnu.org/archive/html/help-make/2013-09/msg00009.html
+uppercase_table := a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O \
+ p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z
+
+uppercase_internal = \
+ $(if $(strip $1), $$(subst $(firstword $1), $(call uppercase_internal, \
+ $(wordlist 2, $(words $1), $1), $2)), $2)
+
+# Convert a string to upper case. Works only on a-z.
+# $1 - The string to convert
+uppercase = \
+ $(strip \
+ $(eval uppercase_result := $(call uppercase_internal, $(uppercase_table), $1)) \
+ $(uppercase_result) \
+ )
+
################################################################################
ifneq ($(DISABLE_CACHE_FIND), true)
@@ -560,8 +583,9 @@
$1_NAME_MACRO := identity
endif
- # Remove any trailing slash from SRC
+ # Remove any trailing slash from SRC and DEST
$1_SRC := $$(patsubst %/,%,$$($1_SRC))
+ $1_DEST := $$(patsubst %/,%,$$($1_DEST))
$$(foreach f, $$(patsubst $$($1_SRC)/%,%,$$($1_FILES)), \
$$(eval $$(call AddFileToCopy, $$($1_SRC)/$$f, \
@@ -592,9 +616,9 @@
WriteFile = \
$(file >$2,$(strip $1))
else
-# Use printf to get consistent behavior on all platforms.
-WriteFile = \
- $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2)
+ # Use printf to get consistent behavior on all platforms.
+ WriteFile = \
+ $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2)
endif
################################################################################
--- a/make/common/NativeCompilation.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/common/NativeCompilation.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -129,6 +129,12 @@
SYSROOT_LDFLAGS := $(BUILD_SYSROOT_LDFLAGS), \
))
+# BUILD toolchain with the C++ linker
+$(eval $(call DefineNativeToolchain, TOOLCHAIN_BUILD_LINK_CXX, \
+ EXTENDS := TOOLCHAIN_BUILD, \
+ LD := $(BUILD_LDCXX), \
+))
+
################################################################################
# Extensions of files handled by this macro.
@@ -209,8 +215,8 @@
$1_$2_OBJ := $3/$$(call replace_with_obj_extension, $$(notdir $2))
# Only continue if this object file hasn't been processed already. This lets the first found
# source file override any other with the same name.
- ifeq (,$$(findstring $$($1_$2_OBJ),$$($1_ALL_OBJS)))
- $1_ALL_OBJS+=$$($1_$2_OBJ)
+ ifeq (,$$(findstring $$($1_$2_OBJ),$$($1_OBJS_SO_FAR)))
+ $1_OBJS_SO_FAR+=$$($1_$2_OBJ)
ifeq (,$$(filter %.s,$2))
# And this is the dependency file for this obj file.
$1_$2_DEP:=$$(patsubst %$(OBJ_SUFFIX),%.d,$$($1_$2_OBJ))
@@ -223,13 +229,18 @@
-include $$($1_$2_DEP_TARGETS)
ifeq ($(TOOLCHAIN_TYPE), microsoft)
- $1_$2_DEBUG_OUT_FLAGS:=-Fd$$(patsubst %$(OBJ_SUFFIX),%.pdb,$$($1_$2_OBJ)) \
- -Fm$$(patsubst %$(OBJ_SUFFIX),%.map,$$($1_$2_OBJ))
+ $1_$2_DEBUG_OUT_FLAGS:=-Fd$$(patsubst %$(OBJ_SUFFIX),%.pdb,$$($1_$2_OBJ))
endif
endif
- $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) | $$($1_BUILD_INFO)
- $(ECHO) $(LOG_INFO) "Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET)))"
+ ifneq ($$($1_$(notdir $2)_CFLAGS)$$($1_$(notdir $2)_CXXFLAGS), )
+ $1_$2_VARDEPS := $$($1_$(notdir $2)_CFLAGS) $$($1_$(notdir $2)_CXXFLAGS)
+ $1_$2_VARDEPS_FILE := $$(call DependOnVariable, $1_$2_VARDEPS, \
+ $$(patsubst %$(OBJ_SUFFIX),%.vardeps,$$($1_$2_OBJ)))
+ endif
+
+ $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) $$($1_$2_VARDEPS_FILE) | $$($1_BUILD_INFO)
+ $$(call LogInfo, Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET))))
ifneq ($(TOOLCHAIN_TYPE), microsoft)
ifeq ($(TOOLCHAIN_TYPE)$$(filter %.s,$2), solstudio)
# The Solaris studio compiler doesn't output the full path to the object file in the
@@ -251,15 +262,17 @@
# setting -showIncludes, all included files are printed. These are filtered out and
# parsed into make dependences.
# Keep as much as possible on one execution line for best performance on Windows
+ $(RM) $$($1_$2_DEP).exitvalue ; \
($(call LogFailures, $$($1_$2_OBJ).log, $$($1_SAFE_NAME)_$$(notdir $2), \
$$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
- $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
+ $(CC_OUT_OPTION)$$($1_$2_OBJ) $2) || echo $$$$? > $$($1_$2_DEP).exitvalue ) \
| $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \
-e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \
- exit `cat $$($1_$2_DEP).exitvalue` ; \
- $(RM) $$($1_$2_DEP).exitvalue ; \\
+ ( test -s $$($1_$2_DEP).exitvalue \
+ && exit `$(CAT) $$($1_$2_DEP).exitvalue` || true ) ; \
($(ECHO) $$@: \\ ; \
- $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) | $(SORT) -u > $$($1_$2_DEP) ; \
+ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) \
+ | $(SORT) -u > $$($1_$2_DEP) ; \
$(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_$2_DEP) > $$($1_$2_DEP_TARGETS)
endif
endif
@@ -286,7 +299,9 @@
# EXCLUDES do not pick source from these directories
# INCLUDE_FILES only compile exactly these files!
# EXCLUDE_FILES with these names
+# EXCLUDE_PATTERN exclude files matching any of these substrings
# EXTRA_FILES List of extra files not in any of the SRC dirs
+# EXTRA_OBJECT_FILES List of extra object files to include when linking
# VERSIONINFO_RESOURCE Input file for RC. Setting this implies that RC will be run
# RC_FLAGS flags for RC.
# MAPFILE mapfile
@@ -430,19 +445,29 @@
$$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
# Find all files in the source trees. Sort to remove duplicates.
- $1_ALL_SRCS := $$(sort $$(call CacheFind,$$($1_SRC)))
+ $1_SRCS := $$(sort $$(call CacheFind,$$($1_SRC)))
+ $1_SRCS := $$(filter $$(NATIVE_SOURCE_EXTENSIONS), $$($1_SRCS))
# Extract the C/C++ files.
- $1_EXCLUDE_FILES:=$$(foreach i,$$($1_SRC),$$(addprefix $$i/,$$($1_EXCLUDE_FILES)))
- $1_INCLUDE_FILES:=$$(foreach i,$$($1_SRC),$$(addprefix $$i/,$$($1_INCLUDE_FILES)))
- ifneq ($$($1_EXCLUDE_FILES),)
- $1_EXCLUDE_FILES:=$$(addprefix %,$$($1_EXCLUDE_FILES))
+ ifneq ($$($1_EXCLUDE_PATTERNS), )
+ # We must not match the exclude pattern against the src root(s).
+ $1_SRCS_WITHOUT_ROOTS := $$($1_SRCS)
+ $$(foreach i,$$($1_SRC),$$(eval $1_SRCS_WITHOUT_ROOTS := $$(patsubst \
+ $$i/%,%, $$($1_SRCS_WITHOUT_ROOTS))))
+ $1_ALL_EXCLUDE_FILES := $$(call containing, $$($1_EXCLUDE_PATTERNS), \
+ $$($1_SRCS_WITHOUT_ROOTS))
endif
- $1_SRCS := $$(filter-out $$($1_EXCLUDE_FILES),$$(filter $$(NATIVE_SOURCE_EXTENSIONS),$$($1_ALL_SRCS)))
- ifneq (,$$(strip $$($1_INCLUDE_FILES)))
- $1_SRCS := $$(filter $$($1_INCLUDE_FILES),$$($1_SRCS))
+ ifneq ($$($1_EXCLUDE_FILES),)
+ $1_ALL_EXCLUDE_FILES += $$($1_EXCLUDE_FILES)
endif
- ifeq (,$$($1_SRCS))
- $$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
+ ifneq ($$($1_ALL_EXCLUDE_FILES),)
+ $1_EXCLUDE_FILES_PAT := $$($1_ALL_EXCLUDE_FILES) \
+ $$(foreach i,$$($1_SRC),$$(addprefix $$i/,$$($1_ALL_EXCLUDE_FILES)))
+ $1_EXCLUDE_FILES_PAT := $$(addprefix %,$$($1_EXCLUDE_FILES_PAT))
+ $1_SRCS := $$(filter-out $$($1_EXCLUDE_FILES_PAT),$$($1_SRCS))
+ endif
+ ifneq ($$($1_INCLUDE_FILES), )
+ $1_INCLUDE_FILES_PAT := $$(foreach i,$$($1_SRC),$$(addprefix $$i/,$$($1_INCLUDE_FILES)))
+ $1_SRCS := $$(filter $$($1_INCLUDE_FILES_PAT),$$($1_SRCS))
endif
# There can be only a single bin dir root, no need to foreach over the roots.
$1_BINS := $$(wildcard $$($1_OBJECT_DIR)/*$(OBJ_SUFFIX))
@@ -466,16 +491,17 @@
$$(error No sources found for $1 when looking inside the dirs $$($1_SRC))
endif
- # Calculate the expected output from compiling the sources (sort to remove duplicates. Also provides
- # a reproducable order on the input files to the linker).
+ # Calculate the expected output from compiling the sources
$1_EXPECTED_OBJS_FILENAMES := $$(call replace_with_obj_extension, $$(notdir $$($1_SRCS)))
- $1_EXPECTED_OBJS:=$$(sort $$(addprefix $$($1_OBJECT_DIR)/,$$($1_EXPECTED_OBJS_FILENAMES)))
+ $1_EXPECTED_OBJS := $$(addprefix $$($1_OBJECT_DIR)/,$$($1_EXPECTED_OBJS_FILENAMES))
# Are there too many object files on disk? Perhaps because some source file was removed?
$1_SUPERFLOUS_OBJS:=$$(sort $$(filter-out $$($1_EXPECTED_OBJS),$$($1_BINS)))
# Clean out the superfluous object files.
ifneq ($$($1_SUPERFLUOUS_OBJS),)
$$(shell $(RM) -f $$($1_SUPERFLUOUS_OBJS))
endif
+ # Sort to remove dupliates and provide a reproducable order on the input files to the linker.
+ $1_ALL_OBJS := $$(sort $$($1_EXPECTED_OBJS) $$($1_EXTRA_OBJECT_FILES))
# Pickup extra OPENJDK_TARGET_OS_TYPE and/or OPENJDK_TARGET_OS dependent variables for CFLAGS.
$1_EXTRA_CFLAGS:=$$($1_CFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_CFLAGS_$(OPENJDK_TARGET_OS))
@@ -593,9 +619,7 @@
# variables used in the call to add_native_source below.
$1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $$($1_SYSROOT_CFLAGS) \
$$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \
- $$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS) \
- $$(foreach s, $$($1_SRCS), \
- $$($1_$$(notdir $$s)_CFLAGS) $$($1_$$(notdir $$s)_CXXFLAGS))
+ $$($1_CC) $$($1_CXX) $$($1_AS) $$($1_ASFLAGS)
$1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
@@ -675,55 +699,62 @@
ifeq ($$($1_STATIC_LIBRARY),)
ifeq ($$($1_DEBUG_SYMBOLS), true)
ifeq ($(ENABLE_DEBUG_SYMBOLS), true)
- ifneq ($(OPENJDK_TARGET_OS), macosx) # no MacOS X support yet
- ifneq ($$($1_OUTPUT_DIR),$$($1_OBJECT_DIR))
- # The dependency on TARGET is needed on windows for debuginfo files
- # to be rebuilt properly.
- $$($1_OUTPUT_DIR)/% : $$($1_OBJECT_DIR)/% $$($1_TARGET)
+ ifneq ($$($1_OUTPUT_DIR), $$($1_OBJECT_DIR))
+ # The dependency on TARGET is needed on windows for debuginfo files
+ # to be rebuilt properly.
+ $$($1_OUTPUT_DIR)/% : $$($1_OBJECT_DIR)/% $$($1_TARGET)
$(CP) $$< $$@
- endif
+ endif
- # Generate debuginfo files.
- ifeq ($(OPENJDK_TARGET_OS), windows)
- $1_EXTRA_LDFLAGS += "-pdb:$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).pdb" \
- "-map:$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).map"
- $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).pdb \
- $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).map
- # No separate command is needed for debuginfo on windows, instead
- # touch target to make sure it has a later time stamp than the debug
- # symbol files to avoid unnecessary relinking on rebuild.
- $1_CREATE_DEBUGINFO_CMDS := $(TOUCH) $$($1_TARGET)
+ # Generate debuginfo files.
+ ifeq ($(OPENJDK_TARGET_OS), windows)
+ $1_EXTRA_LDFLAGS += "-pdb:$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).pdb" \
+ "-map:$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).map"
+ $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).pdb \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).map
+ # No separate command is needed for debuginfo on windows, instead
+ # touch target to make sure it has a later time stamp than the debug
+ # symbol files to avoid unnecessary relinking on rebuild.
+ $1_CREATE_DEBUGINFO_CMDS := $(TOUCH) $$($1_TARGET)
- else ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
- $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).debuginfo
- # Setup the command line creating debuginfo files, to be run after linking.
- # It cannot be run separately since it updates the original target file
- $1_CREATE_DEBUGINFO_CMDS := \
- $(OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) \
- $(CD) $$($1_OUTPUT_DIR) && \
- $(OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
- endif # No MacOS X support
+ else ifneq ($(findstring $(OPENJDK_TARGET_OS), linux solaris), )
+ $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).debuginfo
+ # Setup the command line creating debuginfo files, to be run after linking.
+ # It cannot be run separately since it updates the original target file
+ $1_CREATE_DEBUGINFO_CMDS := \
+ $(OBJCOPY) --only-keep-debug $$($1_TARGET) $$($1_DEBUGINFO_FILES) $$(NEWLINE) \
+ $(CD) $$($1_OUTPUT_DIR) && \
+ $(OBJCOPY) --add-gnu-debuglink=$$($1_DEBUGINFO_FILES) $$($1_TARGET)
- # This dependency dance ensures that debug info files get rebuilt
- # properly if deleted.
- $$($1_TARGET): $$($1_DEBUGINFO_FILES)
- $$($1_DEBUGINFO_FILES): $$($1_EXPECTED_OBJS)
+ else ifeq ($(OPENJDK_TARGET_OS), macosx)
+ $1_DEBUGINFO_FILES := $$($1_OBJECT_DIR)/$$($1_BASENAME).dSYM
+ # On Macosx, the debuginfo generation doesn't touch the linked binary, but
+ # to avoid always relinking, touch it anyway to force a later timestamp than
+ # the dSYM files.
+ $1_CREATE_DEBUGINFO_CMDS := \
+ $(DSYMUTIL) --out $$($1_DEBUGINFO_FILES) $$($1_TARGET) $$(NEWLINE) \
+ $(TOUCH) $$($1_TARGET)
+ endif # OPENJDK_TARGET_OS
- ifeq ($(ZIP_DEBUGINFO_FILES), true)
- $1_DEBUGINFO_ZIP := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).diz
- $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_ZIP))
+ # This dependency dance ensures that debug info files get rebuilt
+ # properly if deleted.
+ $$($1_TARGET): $$($1_DEBUGINFO_FILES)
+ $$($1_DEBUGINFO_FILES): $$($1_ALL_OBJS)
- # The dependency on TARGET is needed for debuginfo files
- # to be rebuilt properly.
- $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
+ ifeq ($(ZIP_DEBUGINFO_FILES), true)
+ $1_DEBUGINFO_ZIP := $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).diz
+ $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_ZIP))
+
+ # The dependency on TARGET is needed for debuginfo files
+ # to be rebuilt properly.
+ $$($1_DEBUGINFO_ZIP): $$($1_DEBUGINFO_FILES) $$($1_TARGET)
$(CD) $$($1_OBJECT_DIR) \
&& $(ZIP) -q $$@ $$(notdir $$($1_DEBUGINFO_FILES))
- else
- $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_FILES))
- endif
+ else
+ $1 += $$(subst $$($1_OBJECT_DIR),$$($1_OUTPUT_DIR),$$($1_DEBUGINFO_FILES))
endif
- endif # !MacOS X
+ endif # $(ENABLE_DEBUG_SYMBOLS)
endif # $1_DEBUG_SYMBOLS
endif # !STATIC_LIBRARY
@@ -750,21 +781,34 @@
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
- $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
+ $1_LD_OBJ_ARG := $$($1_ALL_OBJS)
+
+ # If there are many object files, use an @-file.
+ ifneq ($$(word 17, $$($1_ALL_OBJS)), )
+ $1_OBJ_FILE_LIST := $$($1_OBJECT_DIR)/_$1_objectfilenames.txt
+ ifneq ($(TOOLCHAIN_TYPE),solstudio)
+ $1_LD_OBJ_ARG := $(COMPILER_COMMAND_FILE_FLAG)$$($1_OBJ_FILE_LIST)
+ else
+ # The solstudio linker does not support @-files.
+ $1_LD_OBJ_ARG := `cat $$($1_OBJ_FILE_LIST)`
+ endif
+ endif
+
+ $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
$$($1_VARDEPS_FILE)
+ ifneq ($$($1_OBJ_FILE_LIST), )
+ $$(eval $$(call ListPathsSafely, $1_ALL_OBJS, $$($1_OBJ_FILE_LIST)))
+ endif
+ # Keep as much as possible on one execution line for best performance
+ # on Windows
$(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)" ; \
$(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$(LD_OUT_OPTION)$$@ \
- $$($1_EXPECTED_OBJS) $$($1_RES) \
+ $$($1_LD_OBJ_ARG) $$($1_RES) \
$$($1_LIBS) $$($1_EXTRA_LIBS)) ; \
$$($1_CREATE_DEBUGINFO_CMDS)
$$($1_STRIP_CMD)
- # Touch target to make sure it has a later time stamp than the debug
- # symbol files to avoid unnecessary relinking on rebuild.
- ifeq ($(OPENJDK_TARGET_OS), windows)
- $(TOUCH) $$@
- endif
endif
@@ -775,10 +819,10 @@
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
# Generating a static library, ie object file archive.
- $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
+ $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
$(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
- $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
+ $$($1_AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_ALL_OBJS) \
$$($1_RES))
ifeq ($(STATIC_BUILD), true)
$(GetSymbols)
@@ -796,13 +840,13 @@
$1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
- $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_MANIFEST) \
+ $$($1_TARGET): $$($1_ALL_OBJS) $$($1_RES) $$($1_MANIFEST) \
$$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)" ; \
$(call LogFailures, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link.log, $$($1_SAFE_NAME)_link, \
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
$(EXE_OUT_OPTION)$$($1_TARGET) \
- $$($1_EXPECTED_OBJS) $$($1_RES) \
+ $$($1_ALL_OBJS) $$($1_RES) \
$$($1_LIBS) $$($1_EXTRA_LIBS))
ifeq ($(OPENJDK_TARGET_OS), windows)
ifneq ($$($1_MANIFEST), )
@@ -818,11 +862,6 @@
endif
$$($1_CREATE_DEBUGINFO_CMDS)
$$($1_STRIP_CMD)
- # Touch target to make sure it has a later time stamp than the debug
- # symbol files to avoid unnecessary relinking on rebuild.
- ifeq ($(OPENJDK_TARGET_OS), windows)
- $(TOUCH) $$@
- endif
endif
endef
--- a/make/devkit/Tools.gmk Wed Jan 06 09:39:55 2016 -0500
+++ b/make/devkit/Tools.gmk Wed Jan 06 14:54:24 2016 +0000
@@ -82,7 +82,9 @@
libXi libXi-devel \
libXdmcp libXdmcp-devel \
libXau libXau-devel \
- libgcc
+ libgcc \
+ elfutils elfutils-devel \
+ elfutils-libelf elfutils-libelf-devel
ifeq ($(ARCH),x86_64)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/devkit/createSolarisDevkit.sh Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,148 @@
+#!/bin/bash
+#
+# 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.
+#
+
+# This script creates a devkit for building OpenJDK on Solaris by copying
+# part of a Solaris Studio installation and cretaing a sysroot by installing
+# a limited set of system packages. It is assumed that a suitable pkg
+# publisher is configured for the system where the script is executed.
+#
+# The Solaris Studio installation must contain at least these packages:
+# developer/solarisstudio-124/backend 12.4-1.0.6.0 i--
+# developer/solarisstudio-124/c++ 12.4-1.0.10.0 i--
+# developer/solarisstudio-124/cc 12.4-1.0.4.0 i--
+# developer/solarisstudio-124/library/c++-libs 12.4-1.0.10.0 i--
+# developer/solarisstudio-124/library/math-libs 12.4-1.0.0.1 i--
+# developer/solarisstudio-124/library/studio-gccrt 12.4-1.0.0.1 i--
+# developer/solarisstudio-124/studio-common 12.4-1.0.0.1 i--
+# developer/solarisstudio-124/studio-ja 12.4-1.0.0.1 i--
+# developer/solarisstudio-124/studio-legal 12.4-1.0.0.1 i--
+# developer/solarisstudio-124/studio-zhCN 12.4-1.0.0.1 i--
+# In particular backend 12.4-1.0.6.0 contains a critical patch for the sparc
+# version.
+#
+# erik.joelsson@oracle.com
+
+USAGE="$0 <Solaris Studio installation> <Path to gnu make binary>"
+
+if [ "$1" = "" ] || [ "$2" = "" ]; then
+ echo $USAGE
+ exit 1
+fi
+
+SOLARIS_STUDIO_VERSION=12u4
+SOLARIS_VERSION=11u1
+case `uname -p` in
+ i*)
+ ARCH=x86
+ ;;
+ sparc*)
+ ARCH=sparc
+ ;;
+esac
+
+SOLARIS_STUDIO_SRC=$1
+GNU_MAKE=$2
+
+SCRIPT_DIR="$(cd "$(dirname $0)" > /dev/null && pwd)"
+BUILD_DIR="${SCRIPT_DIR}/../../build/devkit"
+
+DEVKIT_NAME=SS${SOLARIS_STUDIO_VERSION}-Solaris${SOLARIS_VERSION}
+DEVKIT_ROOT=${BUILD_DIR}/${DEVKIT_NAME}
+BUNDLE_NAME=${DEVKIT_NAME}.tar.gz
+BUNDLE=${BUILD_DIR}/${BUNDLE_NAME}
+INSTALL_ROOT=${BUILD_DIR}/install-root
+SYSROOT=${DEVKIT_ROOT}/sysroot
+SOLARIS_STUDIO_SUBDIR=SS${SOLARIS_STUDIO_VERSION}
+SOLARIS_STUDIO_DIR=${DEVKIT_ROOT}/${SOLARIS_STUDIO_SUBDIR}
+
+# Extract the publisher from the system
+if [ -z "${PUBLISHER_URI}" ]; then
+ PUBLISHER_URI="$(pkg publisher solaris | grep URI | awk '{ print $3 }')"
+fi
+
+if [ ! -d $INSTALL_ROOT ]; then
+ echo "Creating $INSTALL_ROOT and installing packages"
+ pkg image-create $INSTALL_ROOT
+ pkg -R $INSTALL_ROOT set-publisher -P -g ${PUBLISHER_URI} solaris
+ pkg -R $INSTALL_ROOT install --accept $(cat solaris11.1-package-list.txt)
+else
+ echo "Skipping installing packages"
+fi
+
+if [ ! -d $SYSROOT ]; then
+ echo "Copying from $INSTALL_ROOT to $SYSROOT"
+ mkdir -p $SYSROOT
+ cp -rH $INSTALL_ROOT/lib $SYSROOT/
+ mkdir $SYSROOT/usr $DEVKIT_ROOT/gnu
+ # Some of the tools in sysroot are needed in the OpenJDK build but cannot be
+ # run from their current location due to relative runtime paths in the
+ # binaries. Move the sysroot/usr/bin directory to the outer bin and have them
+ # be runnable from there to force them to link to the system libraries
+ cp -rH $INSTALL_ROOT/usr/bin $DEVKIT_ROOT
+ cp -rH $INSTALL_ROOT/usr/gnu/bin $DEVKIT_ROOT/gnu/
+ cp -rH $INSTALL_ROOT/usr/lib $SYSROOT/usr/
+ cp -rH $INSTALL_ROOT/usr/include $SYSROOT/usr/
+ pkg -R $INSTALL_ROOT list > $SYSROOT/pkg-list.txt
+else
+ echo "Skipping copying to $SYSROOT"
+fi
+
+if [ ! -d $SOLARIS_STUDIO_DIR ]; then
+ echo "Copying Solaris Studio from $SOLARIS_STUDIO_SRC"
+ cp -rH $SOLARIS_STUDIO_SRC ${SOLARIS_STUDIO_DIR%/*}
+ mv ${SOLARIS_STUDIO_DIR%/*}/${SOLARIS_STUDIO_SRC##*/} $SOLARIS_STUDIO_DIR
+ # Solaris Studio 12.4 requires /lib/libmmheap.so.1 to run, but this lib is not
+ # installed by default on all Solaris systems. Sneak it in from the sysroot to
+ # make it run OOTB on more systems.
+ cp $SYSROOT/lib/libmmheap.so.1 $SOLARIS_STUDIO_DIR/lib/compilers/sys/
+else
+ echo "Skipping copying of Solaris Studio"
+fi
+
+echo "Copying gnu make to $DEVKIT_ROOT/bin"
+mkdir -p $DEVKIT_ROOT/bin
+cp $GNU_MAKE $DEVKIT_ROOT/bin/
+if [ ! -e $DEVKIT_ROOT/bin/gmake ]; then
+ ln -s make $DEVKIT_ROOT/bin/gmake
+fi
+
+# Create the devkit.info file
+echo Creating devkit.info
+INFO_FILE=$DEVKIT_ROOT/devkit.info
+rm -f $INFO_FILE
+echo "# This file describes to configure how to interpret the contents of this devkit" >> $INFO_FILE
+echo "DEVKIT_NAME=\"Solaris Studio $SOLARIS_STUDIO_VERSION - Solaris $SOLARIS_VERSION - $ARCH\"" >> $INFO_FILE
+echo "DEVKIT_TOOLCHAIN_PATH=\"\$DEVKIT_ROOT/$SOLARIS_STUDIO_SUBDIR/bin:\$DEVKIT_ROOT/bin\"" >> $INFO_FILE
+echo "DEVKIT_EXTRA_PATH=\"\$DEVKIT_ROOT/bin\"" >> $INFO_FILE
+echo "DEVKIT_SYSROOT=\"\$DEVKIT_ROOT/sysroot\"" >> $INFO_FILE
+
+if [ ! -e $BUNDLE ]; then
+ echo "Creating $BUNDLE from $DEVKIT_ROOT"
+ cd $DEVKIT_ROOT/..
+ tar zcf $BUNDLE $DEVKIT_NAME
+else
+ echo "Skipping creation of $BUNDLE"
+fi
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/devkit/solaris11.1-package-list.txt Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,157 @@
+compress/bzip2@1.0.6-0.175.1.0.0.24.0
+consolidation/X/X-incorporation@0.5.11-0.175.1.21.0.3.1357
+consolidation/desktop/desktop-incorporation@0.5.11-0.175.1.21.0.4.0
+consolidation/install/install-incorporation@0.5.11-0.175.2.0.0.5.0
+consolidation/ips/ips-incorporation@0.5.11-0.175.1.20.0.3.0
+consolidation/l10n/l10n-incorporation@0.5.11-0.175.1.16.0.2.2
+consolidation/osnet/osnet-incorporation@0.5.11-0.175.1.21.0.4.2
+consolidation/sic_team/sic_team-incorporation@0.5.11-0.175.2.0.0.39.0
+consolidation/solaris_re/solaris_re-incorporation@0.5.11-0.175.2.4.0.4.0
+consolidation/sunpro/sunpro-incorporation@0.5.11-0.175.1.19.0.4.0
+crypto/ca-certificates@0.5.11-0.175.1.0.0.24.2
+database/berkeleydb-5@5.1.25-0.175.1.0.0.24.0
+database/mysql-51/library@5.1.37-0.175.1.10.0.5.0
+database/sqlite-3@3.7.14.1-0.175.1.10.0.4.0
+developer/base-developer-utilities@0.5.11-0.175.1.11.0.1.2
+developer/gnu-binutils@2.21.1-0.175.1.0.0.24.0
+developer/macro/cpp@0.5.11-0.175.1.19.0.4.0
+driver/management/bmc@0.5.11-0.175.1.0.0.24.2
+driver/management/ipmi@0.5.11-0.175.1.6.0.3.2
+driver/serial/usbser@0.5.11-0.175.1.0.0.24.2
+driver/storage/mpt@0.5.11-0.175.1.18.0.3.2
+image/library/libjpeg@6.0.2-0.175.0.0.0.0.0
+image/library/libpng@1.4.11-0.175.1.0.0.16.0
+image/library/libtiff@3.9.5-0.175.1.15.0.2.0
+library/apr-13@1.3.9-0.175.1.0.0.24.0
+library/apr-util-13@1.3.9-0.175.1.0.0.24.0
+library/apr-util-13/apr-ldap@1.3.9-0.175.1.0.0.24.0
+library/apr-util-13/dbd-mysql@1.3.9-0.175.1.0.0.24.0
+library/apr-util-13/dbd-sqlite@1.3.9-0.175.1.0.0.24.0
+library/database/gdbm@1.8.3-0.175.1.0.0.24.0
+library/expat@2.1.0-0.175.1.0.0.24.0
+library/libffi@3.0.9-0.175.0.0.0.0.0
+library/libidn@1.19-0.175.1.0.0.24.0
+library/libtecla@1.6.1-0.175.1.0.0.24.0
+library/libxml2@2.7.6-0.175.1.7.0.3.0
+library/libxslt@1.1.26-0.175.1.11.0.4.0
+library/ncurses@5.7-0.175.1.0.0.15.0
+library/nspr@4.9.5-0.175.2.0.0.39.0
+library/perl-5/sun-solaris-512@0.5.11-0.175.1.11.0.1.2
+library/print/cups-libs@1.4.5-0.175.1.8.0.3.0
+library/python-2/cherrypy@3.1.2-0.175.1.0.0.24.0
+library/python-2/cherrypy-26@3.1.2-0.175.1.0.0.24.0
+library/python-2/jsonrpclib@0.1.3-0.175.2.0.0.42.1
+library/python-2/jsonrpclib-26@0.1.3-0.175.2.0.0.42.1
+library/python-2/libxml2-26@2.7.6-0.175.1.7.0.3.0
+library/python-2/libxsl-26@1.1.26-0.175.1.11.0.4.0
+library/python-2/lxml@2.3.3-0.175.1.0.0.24.0
+library/python-2/lxml-26@2.3.3-0.175.1.0.0.24.0
+library/python-2/m2crypto@0.21.1-0.175.1.0.0.24.0
+library/python-2/m2crypto-26@0.21.1-0.175.1.0.0.24.0
+library/python-2/mako@0.4.1-0.175.1.0.0.24.0
+library/python-2/mako-26@0.4.1-0.175.1.0.0.24.0
+library/python-2/ply@3.1-0.175.1.0.0.24.0
+library/python-2/ply-26@3.1-0.175.1.0.0.24.0
+library/python-2/pybonjour@1.1.1-0.175.1.0.0.24.0
+library/python-2/pybonjour-26@1.1.1-0.175.1.0.0.24.0
+library/python-2/pycurl@7.19.0.1-0.175.1.0.0.24.0
+library/python-2/pycurl-26@7.19.0.1-0.175.1.0.0.24.0
+library/python-2/pyopenssl@0.11-0.175.1.0.0.24.0
+library/python-2/pyopenssl-26@0.11-0.175.1.0.0.24.0
+library/python-2/python-extra-26@2.6.4-0.175.1.0.0.15.0
+library/python-2/simplejson-26@2.1.2-0.175.1.7.0.4.0
+library/readline@5.2-0.175.1.0.0.24.0
+library/security/nss@4.14.3-0.175.2.0.0.39.0
+library/security/openssl@1.0.0.13-0.175.1.21.0.2.0
+library/security/trousers@0.3.6-0.175.1.0.0.24.0
+library/zlib@1.2.3-0.175.1.0.0.24.0
+media/cdrtools@3.0-0.175.1.21.0.4.0
+media/xorriso@0.6.0-0.175.1.0.0.24.0
+network/bridging@0.5.11-0.175.1.12.0.3.2
+package/pkg@0.5.11-0.175.1.20.0.3.0
+package/pkg/system-repository@0.5.11-0.175.1.9.0.1.0
+package/pkg/zones-proxy@0.5.11-0.175.1.0.0.24.0
+package/svr4@0.5.11-0.175.1.7.0.3.2
+print/cups@1.4.5-0.175.1.8.0.3.0
+release/name@0.5.11-0.175.2.4.0.4.0
+runtime/perl-512@5.12.5-0.175.1.8.0.4.0
+runtime/python-26@2.6.8-0.175.1.17.0.4.0
+service/network/dns/mdns@0.5.11-0.175.1.0.0.24.2
+service/network/slp@0.5.11-0.175.1.0.0.24.2
+service/security/gss@0.5.11-0.175.1.0.0.24.2
+service/security/kerberos-5@0.5.11-0.175.1.18.0.2.2
+shell/bash@4.1.9-0.175.1.13.0.1.0
+shell/ksh93@93.21.0.20110208-0.175.1.19.0.2.0
+system/boot-environment-utilities@0.5.11-0.175.1.9.0.1.2
+system/boot/grub@1.99-0.175.1.14.0.2.2
+system/boot/wanboot@0.5.11-0.175.1.0.0.24.2
+system/core-os@0.5.11-0.175.1.20.0.4.2
+system/data/keyboard/keytables@0.5.11-0.175.1.0.0.24.2
+system/data/terminfo/terminfo-core@0.5.11-0.175.1.14.0.3.2
+system/data/timezone@0.5.11-0.175.2.5.0.2.0
+system/device-administration@0.5.11-0.175.1.9.0.2.2
+system/dtrace@0.5.11-0.175.1.20.0.4.2
+system/dynamic-reconfiguration@0.5.11-0.175.1.13.0.2.2
+system/fault-management@0.5.11-0.175.1.18.0.4.2
+system/file-system/hsfs@0.5.11-0.175.1.0.0.24.2
+system/file-system/pcfs@0.5.11-0.175.1.0.0.24.2
+system/file-system/ufs@0.5.11-0.175.1.18.0.3.2
+system/file-system/zfs@0.5.11-0.175.1.21.0.3.2
+system/header@0.5.11-0.175.1.20.0.4.2
+system/install@0.5.11-0.175.1.0.0.24.1736
+system/install/auto-install/auto-install-common@0.5.11-0.175.1.18.0.3.1736
+system/install/configuration@0.5.11-0.175.1.10.0.3.1736
+system/install/locale@0.5.11-0.175.1.0.0.23.1134
+system/io/infiniband@0.5.11-0.175.1.20.0.4.2
+system/io/ultra-wideband@0.5.11-0.175.1.0.0.24.2
+system/io/usb@0.5.11-0.175.1.19.0.2.2
+system/kernel@0.5.11-0.175.1.21.0.4.2
+system/kernel/cpu-counters@0.5.11-0.175.1.17.0.1.2
+system/kernel/platform@0.5.11-0.175.1.21.0.4.2
+system/keyboard/keyboard-utilities@0.5.11-0.175.1.0.0.24.2
+system/library@0.5.11-0.175.1.20.0.3.2
+system/library/boot-management@0.5.11-0.175.1.19.0.1.2
+system/library/c++-runtime@0.5.11-0.175.1.19.0.4.0
+system/library/freetype-2@2.4.11-0.175.1.18.0.1.1350
+system/library/gcc-3-runtime@3.4.3-0.175.1.0.0.24.0
+system/library/iconv/utf-8@0.5.11-0.175.1.9.0.1.1150
+system/library/install@0.5.11-0.175.1.18.0.3.1736
+system/library/libdbus@1.2.28-0.175.1.16.0.2.0
+system/library/math@0.5.11-0.175.1.19.0.4.0
+system/library/mmheap@0.5.11-0.175.1.19.0.4.0
+system/library/security/gss@0.5.11-0.175.1.18.0.3.2
+system/library/security/gss/diffie-hellman@0.5.11-0.175.1.0.0.24.2
+system/library/security/gss/spnego@0.5.11-0.175.1.16.0.1.2
+system/library/security/libsasl@0.5.11-0.175.1.0.0.24.2
+system/library/storage/libdiskmgt@0.5.11-0.175.1.5.0.3.2
+system/library/storage/scsi-plugins@0.5.11-0.175.1.0.0.24.2
+system/library/storage/snia-ima@0.5.11-0.175.1.0.0.24.2
+system/library/storage/suri@0.5.11-0.175.1.0.0.24.2
+system/linker@0.5.11-0.175.1.20.0.1.2
+system/network@0.5.11-0.175.1.20.0.3.2
+system/picl@0.5.11-0.175.1.17.0.3.2
+system/resource-mgmt/resource-pools@0.5.11-0.175.1.0.0.24.2
+system/storage/iscsi/iscsi-initiator@0.5.11-0.175.1.19.0.3.2
+system/storage/iscsi/iscsi-iser@0.5.11-0.175.1.20.0.3.2
+system/system-events@0.5.11-0.175.1.0.0.24.2
+system/xopen/xcu4@0.5.11-0.175.1.13.0.4.2
+system/zones@0.5.11-0.175.1.17.0.4.2
+system/zones/brand/brand-solaris@0.5.11-0.175.1.17.0.4.2
+text/spelling-utilities@0.5.11-0.175.1.0.0.24.2
+web/curl@7.21.2-0.175.1.18.0.3.0
+web/server/apache-22@2.2.27-0.175.1.19.0.4.0
+web/server/apache-22/module/apache-wsgi-26@3.3-0.175.1.0.0.24.0
+x11/header/x11-protocols@7.7-0.175.1.0.0.24.1317
+x11/library/libice@1.0.8-0.175.1.0.0.24.1317
+x11/library/libpthread-stubs@0.3-0.175.1.0.0.24.1317
+x11/library/libsm@1.2.1-0.175.1.0.0.24.1317
+x11/library/libx11@1.5.0-0.175.1.8.0.4.1336
+x11/library/libxau@1.0.7-0.175.1.0.0.24.1317
+x11/library/libxcb@1.8.1-0.175.1.8.0.3.1332
+x11/library/libxdmcp@1.1.1-0.175.1.0.0.24.1317
+x11/library/libxevie@1.0.3-0.175.1.0.0.24.1317
+x11/library/libxext@1.3.1-0.175.1.8.0.3.1332
+x11/library/libxrender@0.9.7-0.175.1.8.0.3.1332
+x11/library/libxscrnsaver@1.2.2-0.175.1.0.0.24.1317
+x11/library/libxtst@1.2.1-0.175.1.8.0.3.1332
+x11/library/toolkit/libxt@1.1.3-0.175.1.8.0.3.1332
--- a/make/jprt.properties Wed Jan 06 09:39:55 2016 -0500
+++ b/make/jprt.properties Wed Jan 06 14:54:24 2016 +0000
@@ -69,9 +69,20 @@
jprt.productOpen.build.configure.args=${jprt.product.build.configure.args} --enable-openjdk-only
jprt.optimizedOpen.build.configure.args=${jprt.product.build.configure.args} --enable-openjdk-only
-# Select build flavors and build targets
-jprt.build.flavors=${my.is.hotspot.job ? ${my.build.flavors.hotspot} : ${my.build.flavors.default}}
-jprt.build.targets=${my.is.hotspot.job ? ${my.build.targets.hotspot} : ${my.build.targets.default}}
+
+# hotspot testset has custom build flavors and build targets
+my.jprt.testsetHasCustomBuildFlavors.hotspot=true
+my.jprt.testsetHasCustomBuildTargets.hotspot=true
+
+# determine if the specified testset has custom build flavors or build targets
+my.jprt.testsetHasCustomBuildFlavors=${my.jprt.testsetHasCustomBuildFlavors.${jprt.test.set}}
+my.jprt.testsetHasCustomBuildTargets=${my.jprt.testsetHasCustomBuildTargets.${jprt.test.set}}
+
+# Select build flavors and build targets based on the specified testset
+jprt.build.flavors=${my.jprt.testsetHasCustomBuildFlavors ? \
+ ${my.build.flavors.${jprt.test.set}} : ${my.build.flavors.default}}
+jprt.build.targets=${my.jprt.testsetHasCustomBuildTargets ? \
+ ${my.build.targets.${jprt.test.set}} : ${my.build.targets.default}}
# Select test targets - jprt default for jprt.test.set is "default"
jprt.test.targets=${my.test.targets.${jprt.test.set}}
@@ -131,6 +142,8 @@
--with-devkit=$GCC492_OEL64_HOME
jprt.macosx_x64.build.configure.args= \
--with-devkit=$XCODE63_MACOSX109_HOME
+jprt.solaris.build.configure.args= \
+ --with-devkit=$SS124_11u1_HOME
jprt.windows_i586.build.configure.args= \
--with-devkit=$VS2013SP4_HOME \
${jprt.i586.build.configure.args}
--- a/modules.xml Wed Jan 06 09:39:55 2016 -0500
+++ b/modules.xml Wed Jan 06 14:54:24 2016 +0000
@@ -223,6 +223,10 @@
<to>jdk.dev</to>
</export>
<export>
+ <name>jdk.internal.math</name>
+ <to>java.desktop</to>
+ </export>
+ <export>
<name>jdk.internal.misc</name>
<to>java.corba</to>
<to>java.desktop</to>
@@ -295,6 +299,7 @@
<to>jdk.security.jgss</to>
<to>jdk.snmp</to>
<to>jdk.vm.ci</to>
+ <to>jdk.zipfs</to>
<to>java.instrument</to>
</export>
<export>
@@ -428,6 +433,7 @@
<to>java.naming</to>
<to>java.rmi</to>
<to>java.security.jgss</to>
+ <to>java.security.sasl</to>
<to>java.smartcardio</to>
<to>jdk.crypto.ec</to>
<to>jdk.crypto.mscapi</to>
@@ -437,6 +443,7 @@
<to>jdk.jartool</to>
<to>jdk.policytool</to>
<to>jdk.security.auth</to>
+ <to>jdk.security.jgss</to>
</export>
<export>
<name>sun.security.x509</name>
--- a/nashorn/.hgtags Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/.hgtags Wed Jan 06 14:54:24 2016 +0000
@@ -331,3 +331,5 @@
9d52f9bb589c4caa3617fe1cf11c72512ab8e973 jdk-9+95
d52c09d5d98a81ee6102a25f662ec4b9ae614163 jdk-9+96
2beaef2b6a880c0bff8c9f57ffca33477d647f8b jdk-9+97
+68a36216f70c0de4c7e36f8978995934fc72ec03 jdk-9+98
+74ddd1339c57cf2c2a13e34e1760006c2e54d1fc jdk-9+99
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -59,6 +59,8 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATIONKEY;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SETTER_PREFIX;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.TYPE_OBJECT;
@@ -272,7 +274,7 @@
addField(cv, name, OBJECT_DESC);
}
- static void newFunction(final MethodGenerator mi, final String className, final MemberInfo memInfo, final List<MemberInfo> specs) {
+ static void newFunction(final MethodGenerator mi, final String objName, final String className, final MemberInfo memInfo, final List<MemberInfo> specs) {
final boolean arityFound = (memInfo.getArity() != MemberInfo.DEFAULT_ARITY);
mi.loadLiteral(memInfo.getName());
@@ -291,6 +293,10 @@
mi.push(memInfo.getArity());
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY, SCRIPTFUNCTION_SETARITY_DESC);
}
+
+ mi.dup();
+ mi.loadLiteral(memInfo.getDocumentationKey(objName));
+ mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETDOCUMENTATIONKEY, SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC);
}
static void linkerAddGetterSetter(final MethodGenerator mi, final String className, final MemberInfo memInfo) {
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -42,6 +42,8 @@
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATIONKEY;
+import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE_DESC;
import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE;
@@ -159,6 +161,11 @@
mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETARITY,
SCRIPTFUNCTION_SETARITY_DESC);
}
+
+ mi.loadThis();
+ mi.loadLiteral(scriptClassInfo.getName());
+ mi.invokeVirtual(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_SETDOCUMENTATIONKEY,
+ SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC);
}
mi.returnVoid();
mi.computeMaxs();
@@ -199,7 +206,7 @@
continue;
}
mi.loadThis();
- newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
+ newFunction(mi, scriptClassInfo.getName(), scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
mi.putField(className, memInfo.getJavaName(), OBJECT_DESC);
}
}
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Wed Jan 06 14:54:24 2016 +0000
@@ -544,4 +544,25 @@
void setArity(final int arity) {
this.arity = arity;
}
+
+ String getDocumentationKey(final String objName) {
+ if (kind == Kind.FUNCTION) {
+ StringBuilder buf = new StringBuilder(objName);
+ switch (where) {
+ case CONSTRUCTOR:
+ break;
+ case PROTOTYPE:
+ buf.append(".prototype");
+ break;
+ case INSTANCE:
+ buf.append(".this");
+ break;
+ }
+ buf.append('.');
+ buf.append(name);
+ return buf.toString();
+ }
+
+ return null;
+ }
}
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -142,7 +142,7 @@
continue;
}
mi.loadThis();
- newFunction(mi, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
+ newFunction(mi, scriptClassInfo.getName(), scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
mi.putField(className, memInfo.getJavaName(), OBJECT_DESC);
}
}
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Wed Jan 06 14:54:24 2016 +0000
@@ -270,6 +270,7 @@
} else {
memInfo.setName(name == null ? methodName : name);
}
+
memInfo.setAttributes(attributes == null ? MemberInfo.DEFAULT_ATTRIBUTES : attributes);
memInfo.setArity((arity == null)? MemberInfo.DEFAULT_ARITY : arity);
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Wed Jan 06 14:54:24 2016 +0000
@@ -170,7 +170,7 @@
if (memInfo.isInstanceFunction()) {
super.visitVarInsn(ALOAD, 0);
- ClassGenerator.newFunction(delegateMV, scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
+ ClassGenerator.newFunction(delegateMV, scriptClassInfo.getName(), scriptClassInfo.getJavaName(), memInfo, scriptClassInfo.findSpecializations(memInfo.getJavaName()));
super.visitFieldInsn(PUTFIELD, scriptClassInfo.getJavaName(),
memInfo.getJavaName(), OBJECT_DESC);
}
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Wed Jan 06 14:54:24 2016 +0000
@@ -118,6 +118,8 @@
static final String SCRIPTFUNCTION_TYPE = TYPE_SCRIPTFUNCTION.getInternalName();
static final String SCRIPTFUNCTION_SETARITY = "setArity";
static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE);
+ static final String SCRIPTFUNCTION_SETDOCUMENTATIONKEY = "setDocumentationKey";
+ static final String SCRIPTFUNCTION_SETDOCUMENTATIONKEY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING);
static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype";
static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT);
static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin";
--- a/nashorn/make/build-benchmark.xml Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/make/build-benchmark.xml Wed Jan 06 14:54:24 2016 +0000
@@ -314,7 +314,7 @@
classpath="${run.test.classpath}"
fork="true"
dir=".">
- <jvmarg line="${ext.class.path}"/>
+ <jvmarg line="${boot.class.path}"/>
<jvmarg line="${run.test.jvmargs.octane} -Xms${run.test.xms} -Xmx${run.test.xmx}"/>
<!-- pass on all properties prefixed with 'nashorn' to the runtime -->
<syspropertyset>
@@ -387,7 +387,7 @@
classpath="${run.test.classpath}"
fork="true"
dir=".">
- <jvmarg line="${ext.class.path}"/>
+ <jvmarg line="${boot.class.path}"/>
<jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
<arg value="-timezone=PST"/>
<arg value="--class-cache-size=50"/>
--- a/nashorn/make/build.xml Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/make/build.xml Wed Jan 06 14:54:24 2016 +0000
@@ -48,12 +48,12 @@
<condition property="git.executable" value="/usr/local/bin/git" else="git">
<available file="/usr/local/bin/git"/>
</condition>
- <!-- check if testng.jar is avaiable, and download it if it isn't -->
+ <!-- check if testng.jar is available, and download it if it isn't -->
<available property="testng.already.present" file="${file.reference.testng.jar}"/>
<antcall target="get-testng"/>
<available property="testng.available" file="${file.reference.testng.jar}"/>
- <!-- check if asmtools-6.0.jar is avaiable, and download it if it isn't -->
+ <!-- check if asmtools-6.0.jar is available, and download it if it isn't -->
<!--
<available property="asmtools.already.present" file="${file.reference.asmtools.jar}"/>
<antcall target="get-asmtools"/>
@@ -84,6 +84,12 @@
<condition property="jfr.options" value="${run.test.jvmargs.jfr}" else="">
<istrue value="${jfr}"/>
</condition>
+
+ <condition property="test-sys-prop-no-security.os.not.windows">
+ <not>
+ <os family="windows"/>
+ </not>
+ </condition>
</target>
<!-- check minimum ant version required to be 1.8.4 -->
@@ -408,6 +414,13 @@
permission java.util.PropertyPermission "nashorn.test.*", "read";
};
+grant codeBase "file:/${basedir}/test/script/basic/apply_to_call/*" {
+ permission java.io.FilePermission "${basedir}/test/script/-", "read";
+ permission java.io.FilePermission "$${user.dir}", "read";
+ permission java.util.PropertyPermission "user.dir", "read";
+ permission java.util.PropertyPermission "nashorn.test.*", "read";
+};
+
grant codeBase "file:/${basedir}/test/script/basic/parser/*" {
permission java.io.FilePermission "${basedir}/test/script/-", "read";
permission java.io.FilePermission "$${user.dir}", "read";
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java Wed Jan 06 14:54:24 2016 +0000
@@ -790,7 +790,7 @@
*/
@SuppressWarnings("unused")
private Object getPropertyGetterHandle(final Object id) {
- return propertyGetters.get(id);
+ return propertyGetters.get(String.valueOf(id));
}
// Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Console.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,7 @@
package jdk.nashorn.tools.jjs;
+import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -34,21 +35,24 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.function.Function;
import jdk.internal.jline.NoInterruptUnixTerminal;
import jdk.internal.jline.Terminal;
import jdk.internal.jline.TerminalFactory;
import jdk.internal.jline.TerminalFactory.Flavor;
import jdk.internal.jline.WindowsTerminal;
import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.KeyMap;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.history.FileHistory;
class Console implements AutoCloseable {
+ private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB
private final ConsoleReader in;
private final FileHistory history;
Console(final InputStream cmdin, final PrintStream cmdout, final File historyFile,
- final Completer completer) throws IOException {
+ final Completer completer, final Function<String, String> docHelper) throws IOException {
TerminalFactory.registerFlavor(Flavor.WINDOWS, isCygwin()? JJSUnixTerminal::new : JJSWindowsTerminal::new);
TerminalFactory.registerFlavor(Flavor.UNIX, JJSUnixTerminal::new);
in = new ConsoleReader(cmdin, cmdout);
@@ -58,6 +62,7 @@
in.setHistory(history = new FileHistory(historyFile));
in.addCompleter(completer);
Runtime.getRuntime().addShutdownHook(new Thread((Runnable)this::saveHistory));
+ bind(DOCUMENTATION_SHORTCUT, (ActionListener)evt -> showDocumentation(docHelper));
}
String readLine(final String prompt) throws IOException {
@@ -138,4 +143,34 @@
private static boolean isCygwin() {
return System.getenv("SHELL") != null;
}
+
+ private void bind(String shortcut, Object action) {
+ KeyMap km = in.getKeys();
+ for (int i = 0; i < shortcut.length(); i++) {
+ final Object value = km.getBound(Character.toString(shortcut.charAt(i)));
+ if (value instanceof KeyMap) {
+ km = (KeyMap) value;
+ } else {
+ km.bind(shortcut.substring(i), action);
+ }
+ }
+ }
+
+ private void showDocumentation(final Function<String, String> docHelper) {
+ final String buffer = in.getCursorBuffer().buffer.toString();
+ final int cursor = in.getCursorBuffer().cursor;
+ final String doc = docHelper.apply(buffer.substring(0, cursor));
+ try {
+ if (doc != null) {
+ in.println();
+ in.println(doc);
+ in.redrawLine();
+ in.flush();
+ } else {
+ in.beep();
+ }
+ } catch (IOException ex) {
+ throw new IllegalStateException(ex);
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,6 +25,9 @@
package jdk.nashorn.tools.jjs;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
+import java.awt.Desktop;
import java.awt.GraphicsEnvironment;
import java.io.BufferedReader;
import java.io.File;
@@ -33,15 +36,21 @@
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.net.URI;
+import java.util.concurrent.Callable;
import java.util.function.Consumer;
+import java.util.function.Function;
import jdk.internal.jline.console.completer.Completer;
import jdk.internal.jline.console.UserInterruptException;
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeJava;
import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.NativeJavaPackage;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.tools.Shell;
@@ -51,6 +60,8 @@
public final class Main extends Shell {
private Main() {}
+ private static final String DOC_PROPERTY_NAME = "__doc__";
+
static final boolean DEBUG = Boolean.getBoolean("nashorn.jjs.debug");
static final boolean HEADLESS = GraphicsEnvironment.isHeadless();
@@ -109,7 +120,37 @@
final PropertiesHelper propsHelper = new PropertiesHelper(env._classpath);
final NashornCompleter completer = new NashornCompleter(context, global, this, propsHelper);
- try (final Console in = new Console(System.in, System.out, HIST_FILE, completer)) {
+ try (final Console in = new Console(System.in, System.out, HIST_FILE, completer,
+ str -> {
+ try {
+ final Object res = context.eval(global, str, global, "<shell>");
+ if (res != null && res != UNDEFINED) {
+ // Special case Java types: show the javadoc for the class.
+ if (NativeJava.isType(UNDEFINED, res)) {
+ final String typeName = NativeJava.typeName(UNDEFINED, res).toString();
+ final String url = typeName.replace('.', '/').replace('$', '.') + ".html";
+ openBrowserForJavadoc(url);
+ } else if (res instanceof NativeJavaPackage) {
+ final String pkgName = ((NativeJavaPackage)res).getName();
+ final String url = pkgName.replace('.', '/') + "/package-summary.html";
+ openBrowserForJavadoc(url);
+ } else if (res instanceof ScriptObject) {
+ final ScriptObject sobj = (ScriptObject)res;
+ if (sobj.has(DOC_PROPERTY_NAME)) {
+ return toString(sobj.get(DOC_PROPERTY_NAME), global);
+ } else if (sobj instanceof ScriptFunction) {
+ return ((ScriptFunction)sobj).getDocumentation();
+ }
+ }
+
+ // FIXME: better than toString for other cases?
+ return toString(res, global);
+ }
+ } catch (Exception ignored) {
+ }
+ return null;
+ })) {
+
if (globalChanged) {
Context.setGlobal(global);
}
@@ -164,7 +205,7 @@
try {
final Object res = context.eval(global, source, global, "<shell>");
- if (res != ScriptRuntime.UNDEFINED) {
+ if (res != UNDEFINED) {
err.println(toString(res, global));
}
} catch (final Exception exp) {
@@ -218,8 +259,8 @@
final PrintWriter err, final boolean doe) {
try {
final Object res = context.eval(global, source, global, "<shell>");
- if (res != ScriptRuntime.UNDEFINED) {
- err.println(JSType.toString(res));
+ if (res != UNDEFINED) {
+ err.println(toString(res, global));
}
} catch (final Exception e) {
err.println(e);
@@ -228,4 +269,15 @@
}
}
}
+
+ // FIXME: needs to be changed to use javase 9 docs later
+ private static String JAVADOC_BASE = "http://download.java.net/jdk9/docs/api/";
+
+ private static void openBrowserForJavadoc(String relativeUrl) {
+ try {
+ final URI uri = new URI(JAVADOC_BASE + relativeUrl);
+ Desktop.getDesktop().browse(uri);
+ } catch (Exception ignored) {
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PropertiesHelper.java Wed Jan 06 14:54:24 2016 +0000
@@ -31,6 +31,7 @@
import java.util.Collections;
import java.util.List;
import java.util.WeakHashMap;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
@@ -136,6 +137,42 @@
return props;
}
+ // This method creates a regex Pattern to use to do CamelCase
+ // matching. The pattern is derived from user supplied string
+ // containing one or more upper case characters in it.
+ private static Pattern makeCamelCasePattern(final String str) {
+ assert !str.isEmpty();
+
+ final char[] chars = str.toCharArray();
+ final StringBuilder buf = new StringBuilder();
+ boolean seenUpperCase = false;
+
+ // Skip first char for case check. Even if it is upper case,
+ // we do not want to put lower case matching pattern before
+ // the first letter!
+ buf.append(chars[0]);
+
+ for (int idx = 1; idx < chars.length; idx++) {
+ final char ch = chars[idx];
+ if (ch >= 'A' && ch <= 'Z') {
+ seenUpperCase = true;
+ buf.append("[^A-Z]*");
+ }
+ buf.append(ch);
+ }
+
+ if (seenUpperCase) {
+ // match anything at the end!
+ buf.append(".*");
+ try {
+ return Pattern.compile(buf.toString());
+ } catch (Exception exp) {
+ }
+ }
+
+ return null;
+ }
+
/**
* Returns the list of properties of the given object that start with the given prefix.
*
@@ -145,8 +182,21 @@
*/
List<String> getProperties(final Object obj, final String prefix) {
assert prefix != null && !prefix.isEmpty();
- return getProperties(obj).stream()
+ List<String> allProps = getProperties(obj);
+ List<String> props = allProps.stream()
.filter(s -> s.startsWith(prefix))
.collect(Collectors.toList());
+
+ // If no match, try CamelCase completion..
+ if (props.isEmpty()) {
+ final Pattern pat = makeCamelCasePattern(prefix);
+ if (pat != null) {
+ return allProps.stream()
+ .filter(s -> pat.matcher(s).matches())
+ .collect(Collectors.toList());
+ }
+ }
+
+ return props;
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -188,8 +188,6 @@
private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
"ensureInt", int.class, Object.class, int.class);
- private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
- "ensureLong", long.class, Object.class, int.class);
private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
"ensureNumber", double.class, Object.class, int.class);
@@ -1726,7 +1724,7 @@
enterStatement(expressionStatement);
loadAndDiscard(expressionStatement.getExpression());
- assert method.getStackSize() == 0;
+ assert method.getStackSize() == 0 : "stack not empty in " + expressionStatement;
return false;
}
@@ -2241,7 +2239,7 @@
* @param arrayType the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
*/
private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
- assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
+ assert arrayType == Type.INT_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
final Expression[] nodes = arrayLiteralNode.getValue();
final Object presets = arrayLiteralNode.getPresets();
@@ -2389,20 +2387,9 @@
method.convert(Type.OBJECT);
} else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
method.load(((Integer)value).doubleValue());
- } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) {
- method.load(((Integer)value).longValue());
} else {
method.load((Integer)value);
}
- } else if (value instanceof Long) {
- if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
- method.load((Long)value);
- method.convert(Type.OBJECT);
- } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
- method.load(((Long)value).doubleValue());
- } else {
- method.load((Long)value);
- }
} else if (value instanceof Double) {
if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
method.load((Double)value);
@@ -3650,8 +3637,6 @@
private void loadMinusOne() {
if (type.isInteger()) {
method.load(isIncrement ? 1 : -1);
- } else if (type.isLong()) {
- method.load(isIncrement ? 1L : -1L);
} else {
method.load(isIncrement ? 1.0 : -1.0);
}
@@ -4033,23 +4018,66 @@
}
private void loadASSIGN_SHR(final BinaryNode binaryNode) {
- new BinarySelfAssignment(binaryNode) {
+ new SelfModifyingStore<BinaryNode>(binaryNode, binaryNode.lhs()) {
@Override
- protected void op() {
- doSHR();
- }
-
+ protected void evaluate() {
+ new OptimisticOperation(assignNode, new TypeBounds(Type.INT, Type.NUMBER)) {
+ @Override
+ void loadStack() {
+ assert assignNode.getWidestOperandType() == Type.INT;
+ if (isRhsZero(binaryNode)) {
+ loadExpressionAsType(binaryNode.lhs(), Type.INT);
+ } else {
+ loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false);
+ method.shr();
+ }
+ }
+
+ @Override
+ void consumeStack() {
+ if (isOptimistic(binaryNode)) {
+ toUint32Optimistic(binaryNode.getProgramPoint());
+ } else {
+ toUint32Double();
+ }
+ }
+ }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(binaryNode.lhs()));
+ method.convert(assignNode.getType());
+ }
}.store();
}
- private void doSHR() {
- // TODO: make SHR optimistic
- method.shr();
- toUint();
- }
-
- private void toUint() {
- JSType.TO_UINT32_I.invoke(method);
+ private void doSHR(final BinaryNode binaryNode) {
+ new OptimisticOperation(binaryNode, new TypeBounds(Type.INT, Type.NUMBER)) {
+ @Override
+ void loadStack() {
+ if (isRhsZero(binaryNode)) {
+ loadExpressionAsType(binaryNode.lhs(), Type.INT);
+ } else {
+ loadBinaryOperands(binaryNode);
+ method.shr();
+ }
+ }
+
+ @Override
+ void consumeStack() {
+ if (isOptimistic(binaryNode)) {
+ toUint32Optimistic(binaryNode.getProgramPoint());
+ } else {
+ toUint32Double();
+ }
+ }
+ }.emit();
+
+ }
+
+ private void toUint32Optimistic(final int programPoint) {
+ method.load(programPoint);
+ JSType.TO_UINT32_OPTIMISTIC.invoke(method);
+ }
+
+ private void toUint32Double() {
+ JSType.TO_UINT32_DOUBLE.invoke(method);
}
private void loadASSIGN_SUB(final BinaryNode binaryNode) {
@@ -4087,7 +4115,7 @@
// Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
numericBounds.widest), Type.NUMBER);
- forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest);
+ forceConversionSeparation = true;
}
}
loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
@@ -4189,14 +4217,7 @@
}
private void loadSHR(final BinaryNode binaryNode) {
- // Optimize x >>> 0 to (uint)x
- if (isRhsZero(binaryNode)) {
- loadExpressionAsType(binaryNode.lhs(), Type.INT);
- toUint();
- } else {
- loadBinaryOperands(binaryNode);
- doSHR();
- }
+ doSHR(binaryNode);
}
private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
@@ -4467,6 +4488,7 @@
}
} else {
final Type storeType = assignNode.getType();
+ assert storeType != Type.LONG;
if (symbol.hasSlotFor(storeType)) {
// Only emit a convert for a store known to be live; converts for dead stores can
// give us an unnecessary ClassCastException.
@@ -4851,8 +4873,6 @@
method.load(optimistic.getProgramPoint());
if(optimisticType.isInteger()) {
method.invoke(ENSURE_INT);
- } else if(optimisticType.isLong()) {
- method.invoke(ENSURE_LONG);
} else if(optimisticType.isNumber()) {
method.invoke(ENSURE_NUMBER);
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FieldObjectCreator.java Wed Jan 06 14:54:24 2016 +0000
@@ -167,8 +167,7 @@
assert fieldName.equals(getFieldName(fieldIndex, PRIMITIVE_FIELD_TYPE)) || fieldType.isObject() : key + " object keys must store to L*-fields";
assert fieldName.equals(getFieldName(fieldIndex, Type.OBJECT)) || fieldType.isPrimitive() : key + " primitive keys must store to J*-fields";
- loadTuple(method, tuple);
-
+ loadTuple(method, tuple, true);
method.putField(fieldClass, fieldName, fieldDesc);
}
@@ -180,11 +179,7 @@
* @param tuple Tuple to store.
*/
private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) {
- if (JSType.isRepresentableAsInt(index)) {
- method.load((int)index);
- } else {
- method.load(index);
- }
+ loadIndex(method, index);
loadTuple(method, tuple, false); //we don't pack array like objects
method.dynamicSetIndex(callSiteFlags);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Wed Jan 06 14:54:24 2016 +0000
@@ -307,9 +307,7 @@
final Type widest = Type.widest(lhs.getType(), rhs.getType());
boolean isInteger = widest.isInteger();
- boolean isLong = widest.isLong();
-
- double value;
+ final double value;
switch (parent.tokenType()) {
case DIV:
@@ -336,7 +334,8 @@
value = lhs.getNumber() - rhs.getNumber();
break;
case SHR:
- return LiteralNode.newInstance(token, finish, JSType.toUint32(lhs.getInt32() >>> rhs.getInt32()));
+ final long result = JSType.toUint32(lhs.getInt32() >>> rhs.getInt32());
+ return LiteralNode.newInstance(token, finish, JSType.isRepresentableAsInt(result) ? (int) result : (double) result);
case SAR:
return LiteralNode.newInstance(token, finish, lhs.getInt32() >> rhs.getInt32());
case SHL:
@@ -368,12 +367,9 @@
}
isInteger &= JSType.isStrictlyRepresentableAsInt(value);
- isLong &= JSType.isStrictlyRepresentableAsLong(value);
if (isInteger) {
return LiteralNode.newInstance(token, finish, (int)value);
- } else if (isLong) {
- return LiteralNode.newInstance(token, finish, (long)value);
}
return LiteralNode.newInstance(token, finish, value);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Wed Jan 06 14:54:24 2016 +0000
@@ -131,7 +131,6 @@
UNDEFINED(Type.UNDEFINED),
BOOLEAN(Type.BOOLEAN),
INT(Type.INT),
- LONG(Type.LONG),
DOUBLE(Type.NUMBER),
OBJECT(Type.OBJECT);
@@ -272,12 +271,9 @@
}
private static class SymbolConversions {
- private static final byte I2L = 1 << 0;
- private static final byte I2D = 1 << 1;
- private static final byte I2O = 1 << 2;
- private static final byte L2D = 1 << 3;
- private static final byte L2O = 1 << 4;
- private static final byte D2O = 1 << 5;
+ private static final byte I2D = 1 << 0;
+ private static final byte I2O = 1 << 1;
+ private static final byte D2O = 1 << 2;
private byte conversions;
@@ -288,9 +284,6 @@
case INT:
case BOOLEAN:
switch (to) {
- case LONG:
- recordConversion(I2L);
- return;
case DOUBLE:
recordConversion(I2D);
return;
@@ -301,18 +294,6 @@
illegalConversion(from, to);
return;
}
- case LONG:
- switch (to) {
- case DOUBLE:
- recordConversion(L2D);
- return;
- case OBJECT:
- recordConversion(L2O);
- return;
- default:
- illegalConversion(from, to);
- return;
- }
case DOUBLE:
if(to == LvarType.OBJECT) {
recordConversion(D2O);
@@ -340,26 +321,15 @@
if(hasConversion(D2O)) {
symbol.setHasSlotFor(Type.NUMBER);
}
- if(hasConversion(L2O)) {
- symbol.setHasSlotFor(Type.LONG);
- }
if(hasConversion(I2O)) {
symbol.setHasSlotFor(Type.INT);
}
}
if(symbol.hasSlotFor(Type.NUMBER)) {
- if(hasConversion(L2D)) {
- symbol.setHasSlotFor(Type.LONG);
- }
if(hasConversion(I2D)) {
symbol.setHasSlotFor(Type.INT);
}
}
- if(symbol.hasSlotFor(Type.LONG)) {
- if(hasConversion(I2L)) {
- symbol.setHasSlotFor(Type.INT);
- }
- }
}
}
@@ -378,7 +348,7 @@
if(lvarType != null) {
return lvarType;
}
- assert type.isObject();
+ assert type.isObject() : "Unsupported primitive type: " + type;
return LvarType.OBJECT;
}
private static LvarType widestLvarType(final LvarType t1, final LvarType t2) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Wed Jan 06 14:54:24 2016 +0000
@@ -544,7 +544,6 @@
} else {
assert false : type + " cannot be packed!";
}
- //all others are nops, objects aren't packed
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Wed Jan 06 14:54:24 2016 +0000
@@ -41,7 +41,6 @@
import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
import static jdk.nashorn.internal.runtime.JSType.TYPE_DOUBLE_INDEX;
import static jdk.nashorn.internal.runtime.JSType.TYPE_INT_INDEX;
-import static jdk.nashorn.internal.runtime.JSType.TYPE_LONG_INDEX;
import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
import static jdk.nashorn.internal.runtime.JSType.TYPE_UNDEFINED_INDEX;
import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
@@ -535,8 +534,6 @@
switch (getAccessorTypeIndex(forType)) {
case TYPE_INT_INDEX:
return MH.explicitCastArguments(primitiveGetter, primitiveGetter.type().changeReturnType(int.class));
- case TYPE_LONG_INDEX:
- return primitiveGetter;
case TYPE_DOUBLE_INDEX:
return MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE);
case TYPE_OBJECT_INDEX:
@@ -623,7 +620,7 @@
}
assert !isOptimistic;
- //freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b
+ // freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b
final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter);
if (fti == TYPE_OBJECT_INDEX) {
if (fti != ti) {
@@ -638,22 +635,10 @@
case TYPE_INT_INDEX: {
return MH.asType(tgetter, tgetterType.changeReturnType(type));
}
- case TYPE_LONG_INDEX:
- switch (ti) {
- case TYPE_INT_INDEX:
- //get int while an int, truncating cast of long value
- return MH.filterReturnValue(tgetter, JSType.TO_INT32_L.methodHandle);
- case TYPE_LONG_INDEX:
- return primitiveGetter;
- default:
- return MH.asType(tgetter, tgetterType.changeReturnType(type));
- }
case TYPE_DOUBLE_INDEX:
switch (ti) {
case TYPE_INT_INDEX:
return MH.filterReturnValue(tgetter, JSType.TO_INT32_D.methodHandle);
- case TYPE_LONG_INDEX:
- return MH.explicitCastArguments(tgetter, tgetterType.changeReturnType(type));
case TYPE_DOUBLE_INDEX:
assert tgetterType.returnType() == double.class;
return tgetter;
@@ -734,12 +719,9 @@
switch (fti) {
case TYPE_INT_INDEX:
- case TYPE_LONG_INDEX:
switch (ti) {
case TYPE_INT_INDEX:
return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class));
- case TYPE_LONG_INDEX:
- return primitiveSetter;
case TYPE_DOUBLE_INDEX:
return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE);
default:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectCreator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/ObjectCreator.java Wed Jan 06 14:54:24 2016 +0000
@@ -29,6 +29,7 @@
import java.util.List;
import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -156,15 +157,15 @@
MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) {
loadValue(tuple.value, tuple.type);
- if (pack && codegen.useDualFields() && tuple.isPrimitive()) {
+ if (!codegen.useDualFields() || !tuple.isPrimitive()) {
+ method.convert(Type.OBJECT);
+ } else if (pack) {
method.pack();
- } else {
- method.convert(Type.OBJECT);
}
return method;
}
- MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
- return loadTuple(method, tuple, true);
+ MethodEmitter loadIndex(final MethodEmitter method, final long index) {
+ return JSType.isRepresentableAsInt(index) ? method.load((int) index) : method.load((double) index);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SpillObjectCreator.java Wed Jan 06 14:54:24 2016 +0000
@@ -109,8 +109,6 @@
//avoid blowing up the array if we can
if (constantValue instanceof Integer) {
arrayData = arrayData.set(index, ((Integer)constantValue).intValue(), false);
- } else if (constantValue instanceof Long) {
- arrayData = arrayData.set(index, ((Long)constantValue).longValue(), false);
} else if (constantValue instanceof Double) {
arrayData = arrayData.set(index, ((Double)constantValue).doubleValue(), false);
} else {
@@ -169,13 +167,13 @@
final int index = ArrayIndex.getArrayIndex(tuple.key);
assert ArrayIndex.isValidArrayIndex(index);
method.dup();
- method.load(ArrayIndex.toLongIndex(index));
- loadTuple(method, tuple);
+ loadIndex(method, ArrayIndex.toLongIndex(index));
+ loadTuple(method, tuple, false);
method.dynamicSetIndex(callSiteFlags);
} else {
assert property.getKey() instanceof String; // symbol keys not yet supported in object literals
method.dup();
- loadTuple(method, tuple);
+ loadTuple(method, tuple, false);
method.dynamicSet((String) property.getKey(), codegen.getCallSiteFlags(), false);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java Wed Jan 06 14:54:24 2016 +0000
@@ -239,7 +239,7 @@
// currently deoptimize all the way to Object.
return Type.OBJECT;
}
- assert returnType == Type.INT || returnType == Type.LONG || returnType == Type.NUMBER || returnType == Type.OBJECT;
+ assert returnType == Type.INT || returnType == Type.NUMBER || returnType == Type.OBJECT;
return returnType;
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/IntType.java Wed Jan 06 14:54:24 2016 +0000
@@ -72,7 +72,7 @@
@Override
public Type nextWider() {
- return LONG;
+ return NUMBER;
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/LongType.java Wed Jan 06 14:54:24 2016 +0000
@@ -28,20 +28,11 @@
import static jdk.internal.org.objectweb.asm.Opcodes.L2D;
import static jdk.internal.org.objectweb.asm.Opcodes.L2I;
import static jdk.internal.org.objectweb.asm.Opcodes.LADD;
-import static jdk.internal.org.objectweb.asm.Opcodes.LAND;
-import static jdk.internal.org.objectweb.asm.Opcodes.LCMP;
import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0;
import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1;
import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
-import static jdk.internal.org.objectweb.asm.Opcodes.LMUL;
-import static jdk.internal.org.objectweb.asm.Opcodes.LOR;
import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
-import static jdk.internal.org.objectweb.asm.Opcodes.LSHL;
-import static jdk.internal.org.objectweb.asm.Opcodes.LSHR;
import static jdk.internal.org.objectweb.asm.Opcodes.LSTORE;
-import static jdk.internal.org.objectweb.asm.Opcodes.LSUB;
-import static jdk.internal.org.objectweb.asm.Opcodes.LUSHR;
-import static jdk.internal.org.objectweb.asm.Opcodes.LXOR;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
@@ -53,7 +44,7 @@
/**
* Type class: LONG
*/
-class LongType extends BitwiseType {
+class LongType extends Type {
private static final long serialVersionUID = 1L;
private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Long.class, "valueOf", Long.class, long.class);
@@ -82,12 +73,6 @@
}
@Override
- public Type cmp(final MethodVisitor method) {
- method.visitInsn(LCMP);
- return INT;
- }
-
- @Override
public Type load(final MethodVisitor method, final int slot) {
assert slot != -1;
method.visitVarInsn(LLOAD, slot);
@@ -149,88 +134,6 @@
}
@Override
- public Type sub(final MethodVisitor method, final int programPoint) {
- if(programPoint == INVALID_PROGRAM_POINT) {
- method.visitInsn(LSUB);
- } else {
- method.visitInvokeDynamicInsn("lsub", "(JJ)J", MATHBOOTSTRAP, programPoint);
- }
- return LONG;
- }
-
- @Override
- public Type mul(final MethodVisitor method, final int programPoint) {
- if(programPoint == INVALID_PROGRAM_POINT) {
- method.visitInsn(LMUL);
- } else {
- method.visitInvokeDynamicInsn("lmul", "(JJ)J", MATHBOOTSTRAP, programPoint);
- }
- return LONG;
- }
-
- @Override
- public Type div(final MethodVisitor method, final int programPoint) {
- if (programPoint == INVALID_PROGRAM_POINT) {
- JSType.DIV_ZERO_LONG.invoke(method);
- } else {
- method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
- }
- return LONG;
- }
-
- @Override
- public Type rem(final MethodVisitor method, final int programPoint) {
- if (programPoint == INVALID_PROGRAM_POINT) {
- JSType.REM_ZERO_LONG.invoke(method);
- } else {
- method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
- }
- return LONG;
- }
-
- @Override
- public Type shr(final MethodVisitor method) {
- method.visitInsn(LUSHR);
- return LONG;
- }
-
- @Override
- public Type sar(final MethodVisitor method) {
- method.visitInsn(LSHR);
- return LONG;
- }
-
- @Override
- public Type shl(final MethodVisitor method) {
- method.visitInsn(LSHL);
- return LONG;
- }
-
- @Override
- public Type and(final MethodVisitor method) {
- method.visitInsn(LAND);
- return LONG;
- }
-
- @Override
- public Type or(final MethodVisitor method) {
- method.visitInsn(LOR);
- return LONG;
- }
-
- @Override
- public Type xor(final MethodVisitor method) {
- method.visitInsn(LXOR);
- return LONG;
- }
-
- @Override
- public Type neg(final MethodVisitor method, final int programPoint) {
- method.visitInvokeDynamicInsn("lneg", "(J)J", MATHBOOTSTRAP, programPoint);
- return LONG;
- }
-
- @Override
public void _return(final MethodVisitor method) {
method.visitInsn(LRETURN);
}
@@ -246,9 +149,4 @@
method.visitInsn(LCONST_0);
return LONG;
}
-
- @Override
- public Type cmp(final MethodVisitor method, final boolean isCmpG) {
- return cmp(method);
- }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/types/Type.java Wed Jan 06 14:54:24 2016 +0000
@@ -914,7 +914,7 @@
/**
* This is the long singleton, used for all long types
*/
- public static final BitwiseType LONG = putInCache(new LongType());
+ public static final Type LONG = putInCache(new LongType());
/**
* A string singleton
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BinaryNode.java Wed Jan 06 14:54:24 2016 +0000
@@ -70,7 +70,9 @@
TokenType.ASSIGN_DIV,
TokenType.ASSIGN_MOD,
TokenType.ASSIGN_MUL,
- TokenType.ASSIGN_SUB
+ TokenType.ASSIGN_SUB,
+ TokenType.SHR,
+ TokenType.ASSIGN_SHR
})));
/**
@@ -196,9 +198,7 @@
return Type.CHARSEQUENCE;
}
final Type widestOperandType = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
- if(widestOperandType == Type.INT) {
- return Type.LONG;
- } else if (widestOperandType.isNumeric()) {
+ if (widestOperandType.isNumeric()) {
return Type.NUMBER;
}
// We pretty much can't know what it will be statically. Must presume OBJECT conservatively, as we can end
@@ -210,7 +210,7 @@
}
case SHR:
case ASSIGN_SHR:
- return Type.LONG;
+ return Type.NUMBER;
case ASSIGN_SAR:
case ASSIGN_SHL:
case BIT_AND:
@@ -239,10 +239,6 @@
if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
return Type.INT;
}
- final Type widestOperandType = Type.widest(booleanToInt(lhsType), booleanToInt(rhsType));
- if(widestOperandType == Type.INT) {
- return Type.LONG;
- }
return Type.NUMBER;
}
case VOID: {
@@ -565,6 +561,9 @@
if(type == null) {
return widest;
}
+ if (tokenType() == TokenType.ASSIGN_SHR || tokenType() == TokenType.SHR) {
+ return type;
+ }
return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(), rhs.getType())));
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java Wed Jan 06 14:54:24 2016 +0000
@@ -386,8 +386,6 @@
private static Type numberGetType(final Number number) {
if (number instanceof Integer) {
return Type.INT;
- } else if (number instanceof Long) {
- return Type.LONG;
} else if (number instanceof Double) {
return Type.NUMBER;
} else {
@@ -418,6 +416,7 @@
* @return the new literal node
*/
public static LiteralNode<Number> newInstance(final long token, final int finish, final Number value) {
+ assert !(value instanceof Long);
return new NumberLiteralNode(token, finish, value);
}
@@ -776,8 +775,6 @@
assert !elementType.isUnknown();
if (elementType.isInteger()) {
return presetIntArray(value, postsets);
- } else if (elementType.isLong()) {
- return presetLongArray(value, postsets);
} else if (elementType.isNumeric()) {
return presetDoubleArray(value, postsets);
} else {
@@ -847,8 +844,6 @@
private static ArrayType getArrayType(final Type elementType) {
if (elementType.isInteger()) {
return Type.INT_ARRAY;
- } else if (elementType.isLong()) {
- return Type.LONG_ARRAY;
} else if (elementType.isNumeric()) {
return Type.NUMBER_ARRAY;
} else {
@@ -883,8 +878,6 @@
private boolean presetsMatchElementType() {
if (elementType == Type.INT) {
return presets instanceof int[];
- } else if (elementType == Type.LONG) {
- return presets instanceof long[];
} else if (elementType == Type.NUMBER) {
return presets instanceof double[];
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Symbol.java Wed Jan 06 14:54:24 2016 +0000
@@ -82,14 +82,12 @@
public static final int HAS_SLOT = 1 << 10;
/** Is this symbol known to store an int value ? */
public static final int HAS_INT_VALUE = 1 << 11;
- /** Is this symbol known to store a long value ? */
- public static final int HAS_LONG_VALUE = 1 << 12;
/** Is this symbol known to store a double value ? */
- public static final int HAS_DOUBLE_VALUE = 1 << 13;
+ public static final int HAS_DOUBLE_VALUE = 1 << 12;
/** Is this symbol known to store an object value ? */
- public static final int HAS_OBJECT_VALUE = 1 << 14;
+ public static final int HAS_OBJECT_VALUE = 1 << 13;
/** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */
- public static final int HAS_BEEN_DECLARED = 1 << 15;
+ public static final int HAS_BEEN_DECLARED = 1 << 14;
/** Null or name identifying symbol. */
private final String name;
@@ -256,7 +254,6 @@
*/
public int slotCount() {
return ((flags & HAS_INT_VALUE) == 0 ? 0 : 1) +
- ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2) +
((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) +
((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1);
}
@@ -278,7 +275,6 @@
append("slot=").
append(firstSlot).append(' ');
if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); }
- if((flags & HAS_LONG_VALUE) != 0) { sb.append('J'); }
if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); }
if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); }
sb.append(')');
@@ -573,11 +569,6 @@
return typeSlot;
}
typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1);
- if(type.isLong()) {
- assert (flags & HAS_LONG_VALUE) != 0;
- return typeSlot;
- }
- typeSlot += ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2);
if(type.isNumber()) {
assert (flags & HAS_DOUBLE_VALUE) != 0;
return typeSlot;
@@ -595,8 +586,6 @@
public boolean hasSlotFor(final Type type) {
if(type.isBoolean() || type.isInteger()) {
return (flags & HAS_INT_VALUE) != 0;
- } else if(type.isLong()) {
- return (flags & HAS_LONG_VALUE) != 0;
} else if(type.isNumber()) {
return (flags & HAS_DOUBLE_VALUE) != 0;
}
@@ -611,8 +600,6 @@
public void setHasSlotFor(final Type type) {
if(type.isBoolean() || type.isInteger()) {
setFlag(HAS_INT_VALUE);
- } else if(type.isLong()) {
- setFlag(HAS_LONG_VALUE);
} else if(type.isNumber()) {
setFlag(HAS_DOUBLE_VALUE);
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,9 +25,6 @@
package jdk.nashorn.internal.ir.debug;
-import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
-import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.FLAGS_MASK;
-
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -502,6 +499,7 @@
appendOpcode(sb, Opcodes.INVOKEDYNAMIC).append(' ');
final boolean isNashornBootstrap = isNashornBootstrap(bsm);
+ final boolean isNashornMathBootstrap = isNashornMathBootstrap(bsm);
if (isNashornBootstrap) {
sb.append(NashornCallSiteDescriptor.getOperationName((Integer)bsmArgs[0]));
final String decodedName = NameCodec.decode(name);
@@ -529,12 +527,9 @@
} else if (cst instanceof Handle) {
appendHandle(sb, (Handle)cst);
} else if (cst instanceof Integer && isNashornBootstrap) {
- final int c = (Integer)cst;
- final int pp = c >> CALLSITE_PROGRAM_POINT_SHIFT;
- if (pp != 0) {
- sb.append(" pp=").append(pp);
- }
- sb.append(NashornCallSiteDescriptor.toString(c & FLAGS_MASK));
+ NashornCallSiteDescriptor.appendFlags((Integer) cst, sb);
+ } else if (cst instanceof Integer && isNashornMathBootstrap) {
+ sb.append(" pp=").append(cst);
} else {
sb.append(cst);
}
@@ -551,6 +546,10 @@
return "bootstrap".equals(bsm.getName()) && BOOTSTRAP_CLASS_NAME.equals(bsm.getOwner());
}
+ private static boolean isNashornMathBootstrap(final Handle bsm) {
+ return "mathBootstrap".equals(bsm.getName()) && BOOTSTRAP_CLASS_NAME.equals(bsm.getOwner());
+ }
+
private static boolean noFallThru(final int opcode) {
switch (opcode) {
case Opcodes.GOTO:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jan 06 14:54:24 2016 +0000
@@ -1106,8 +1106,6 @@
return new NativeArray(ArrayData.allocate((Object[])obj), this);
} else if (obj instanceof double[]) { // extension
return new NativeArray(ArrayData.allocate((double[])obj), this);
- } else if (obj instanceof long[]) {
- return new NativeArray(ArrayData.allocate((long[])obj), this);
} else if (obj instanceof int[]) {
return new NativeArray(ArrayData.allocate((int[]) obj), this);
} else if (obj instanceof ArrayData) {
@@ -1994,16 +1992,6 @@
}
/**
- * Allocate a new long array.
- *
- * @param initial number values.
- * @return the new array
- */
- public static NativeArray allocate(final long[] initial) {
- return new NativeArray(ArrayData.allocate(initial));
- }
-
- /**
* Allocate a new integer array.
*
* @param initial number values.
@@ -2291,7 +2279,6 @@
new Specialization[] {
new Specialization(GlobalFunctions.PARSEINT_Z),
new Specialization(GlobalFunctions.PARSEINT_I),
- new Specialization(GlobalFunctions.PARSEINT_J),
new Specialization(GlobalFunctions.PARSEINT_OI),
new Specialization(GlobalFunctions.PARSEINT_O) });
this.parseFloat = ScriptFunction.createBuiltin("parseFloat", GlobalFunctions.PARSEFLOAT);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArguments.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArguments.java Wed Jan 06 14:54:24 2016 +0000
@@ -128,12 +128,6 @@
}
@Override
- public boolean delete(final long key, final boolean strict) {
- final int index = ArrayIndex.getArrayIndex(key);
- return isMapped(index) ? deleteMapped(index, strict) : super.delete(key, strict);
- }
-
- @Override
public boolean delete(final double key, final boolean strict) {
final int index = ArrayIndex.getArrayIndex(key);
return isMapped(index) ? deleteMapped(index, strict) : super.delete(key, strict);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Jan 06 14:54:24 2016 +0000
@@ -100,20 +100,38 @@
}
NativeArray(final long length) {
- // TODO assert valid index in long before casting
- this(ArrayData.allocate((int)length));
+ this(ArrayData.allocate(length));
}
NativeArray(final int[] array) {
this(ArrayData.allocate(array));
}
- NativeArray(final long[] array) {
+ NativeArray(final double[] array) {
this(ArrayData.allocate(array));
}
- NativeArray(final double[] array) {
- this(ArrayData.allocate(array));
+ NativeArray(final long[] array) {
+ this(ArrayData.allocate(array.length));
+
+ ArrayData arrayData = this.getArray();
+ Class<?> widest = int.class;
+
+ for (int index = 0; index < array.length; index++) {
+ final long value = array[index];
+
+ if (widest == int.class && JSType.isRepresentableAsInt(value)) {
+ arrayData = arrayData.set(index, (int) value, false);
+ } else if (widest != Object.class && JSType.isRepresentableAsDouble(value)) {
+ arrayData = arrayData.set(index, (double) value, false);
+ widest = double.class;
+ } else {
+ arrayData = arrayData.set(index, (Object) value, false);
+ widest = Object.class;
+ }
+ }
+
+ this.setArray(arrayData);
}
NativeArray(final Object[] array) {
@@ -179,7 +197,7 @@
@Override
public MethodHandle call() {
return Bootstrap.createDynamicCallInvoker(rtype, Object.class, Object.class, Object.class,
- long.class, Object.class);
+ double.class, Object.class);
}
});
}
@@ -210,7 +228,7 @@
@Override
public MethodHandle call() {
return Bootstrap.createDynamicCallInvoker(Object.class, Object.class,
- Undefined.class, Object.class, Object.class, long.class, Object.class);
+ Undefined.class, Object.class, Object.class, double.class, Object.class);
}
});
}
@@ -246,8 +264,9 @@
@Override
public Object getLength() {
- final long length = JSType.toUint32(getArray().length());
- if (length < Integer.MAX_VALUE) {
+ final long length = getArray().length();
+ assert length >= 0L;
+ if (length <= Integer.MAX_VALUE) {
return (int)length;
}
return length;
@@ -445,7 +464,13 @@
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
public static Object length(final Object self) {
if (isArray(self)) {
- return JSType.toUint32(((ScriptObject) self).getArray().length());
+ final long length = ((ScriptObject) self).getArray().length();
+ assert length >= 0L;
+ // Cast to the narrowest supported numeric type to help optimistic type calculator
+ if (length <= Integer.MAX_VALUE) {
+ return (int) length;
+ }
+ return (double) length;
}
return 0;
@@ -1553,7 +1578,7 @@
private final MethodHandle everyInvoker = getEVERY_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
return result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self);
}
}.apply();
@@ -1573,7 +1598,7 @@
private final MethodHandle someInvoker = getSOME_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
return !(result = (boolean)someInvoker.invokeExact(callbackfn, thisArg, val, i, self));
}
}.apply();
@@ -1593,7 +1618,7 @@
private final MethodHandle forEachInvoker = getFOREACH_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
forEachInvoker.invokeExact(callbackfn, thisArg, val, i, self);
return true;
}
@@ -1614,7 +1639,7 @@
private final MethodHandle mapInvoker = getMAP_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
final Object r = mapInvoker.invokeExact(callbackfn, thisArg, val, i, self);
result.defineOwnProperty(ArrayIndex.getArrayIndex(index), r);
return true;
@@ -1644,7 +1669,7 @@
private final MethodHandle filterInvoker = getFILTER_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
if ((boolean)filterInvoker.invokeExact(callbackfn, thisArg, val, i, self)) {
result.defineOwnProperty(ArrayIndex.getArrayIndex(to++), val);
}
@@ -1676,7 +1701,7 @@
private final MethodHandle reduceInvoker = getREDUCE_CALLBACK_INVOKER();
@Override
- protected boolean forEach(final Object val, final long i) throws Throwable {
+ protected boolean forEach(final Object val, final double i) throws Throwable {
// TODO: why can't I declare the second arg as Undefined.class?
result = reduceInvoker.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self);
return true;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -124,7 +124,7 @@
@Override
public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
- if (returnType == int.class || returnType == long.class) {
+ if (returnType == int.class) {
return null;
}
return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
@@ -136,11 +136,6 @@
}
@Override
- public long getLong(final int index) {
- return (long)getDouble(index);
- }
-
- @Override
public double getDouble(final int index) {
return getElem(index);
}
@@ -166,11 +161,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (double)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
setElem(index, value);
return this;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -124,7 +124,7 @@
@Override
public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
- if (returnType == int.class || returnType == long.class) {
+ if (returnType == int.class) {
return null;
}
return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
@@ -136,11 +136,6 @@
}
@Override
- public long getLong(final int index) {
- return (long)getDouble(index);
- }
-
- @Override
public double getDouble(final int index) {
return getElem(index);
}
@@ -166,11 +161,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (double)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
setElem(index, value);
return this;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Wed Jan 06 14:54:24 2016 +0000
@@ -97,7 +97,6 @@
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object apply(final Object self, final Object thiz, final Object array) {
checkCallable(self);
-
final Object[] args = toApplyArgs(array);
if (self instanceof ScriptFunction) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -134,16 +134,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -170,11 +160,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -133,16 +133,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -169,11 +159,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -132,16 +132,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -168,11 +158,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Jan 06 14:54:24 2016 +0000
@@ -185,36 +185,11 @@
}
@Override
- public int getInt(final long key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
- }
-
- @Override
public int getInt(final int key, final int programPoint) {
return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
}
@Override
- public long getLong(final Object key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
- }
-
- @Override
- public long getLong(final double key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
- }
-
- @Override
- public long getLong(final long key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
- }
-
- @Override
- public long getLong(final int key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
- }
-
- @Override
public double getDouble(final Object key, final int programPoint) {
return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@@ -225,11 +200,6 @@
}
@Override
- public double getDouble(final long key, final int programPoint) {
- return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
- }
-
- @Override
public double getDouble(final int key, final int programPoint) {
return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
}
@@ -245,11 +215,6 @@
}
@Override
- public Object get(final long key) {
- return (overrides && super.hasOwnProperty(key)) ? super.get(key) : callAdaptee(__get__, key);
- }
-
- @Override
public Object get(final int key) {
return (overrides && super.hasOwnProperty(key)) ? super.get(key) : callAdaptee(__get__, key);
}
@@ -264,15 +229,6 @@
}
@Override
- public void set(final Object key, final long value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
public void set(final Object key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
super.set(key, value, flags);
@@ -300,15 +256,6 @@
}
@Override
- public void set(final double key, final long value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
public void set(final double key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
super.set(key, value, flags);
@@ -327,42 +274,6 @@
}
@Override
- public void set(final long key, final int value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
- public void set(final long key, final long value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
- public void set(final long key, final double value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
- public void set(final long key, final Object value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
public void set(final int key, final int value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
super.set(key, value, flags);
@@ -372,15 +283,6 @@
}
@Override
- public void set(final int key, final long value, final int flags) {
- if (overrides && super.hasOwnProperty(key)) {
- super.set(key, value, flags);
- } else {
- callAdaptee(__put__, key, value, flags);
- }
- }
-
- @Override
public void set(final int key, final double value, final int flags) {
if (overrides && super.hasOwnProperty(key)) {
super.set(key, value, flags);
@@ -417,15 +319,6 @@
}
@Override
- public boolean has(final long key) {
- if (overrides && super.hasOwnProperty(key)) {
- return true;
- }
-
- return JSType.toBoolean(callAdaptee(Boolean.FALSE, __has__, key));
- }
-
- @Override
public boolean has(final double key) {
if (overrides && super.hasOwnProperty(key)) {
return true;
@@ -444,15 +337,6 @@
}
@Override
- public boolean delete(final long key, final boolean strict) {
- if (overrides && super.hasOwnProperty(key)) {
- return super.delete(key, strict);
- }
-
- return JSType.toBoolean(callAdaptee(Boolean.TRUE, __delete__, key, strict));
- }
-
- @Override
public boolean delete(final double key, final boolean strict) {
if (overrides && super.hasOwnProperty(key)) {
return super.delete(key, strict);
@@ -669,10 +553,6 @@
return JSType.toNumberMaybeOptimistic(callAdaptee(name, args), programPoint);
}
- private long callAdapteeLong(final int programPoint, final String name, final Object... args) {
- return JSType.toLongMaybeOptimistic(callAdaptee(name, args), programPoint);
- }
-
private int callAdapteeInt(final int programPoint, final String name, final Object... args) {
return JSType.toInt32MaybeOptimistic(callAdaptee(name, args), programPoint);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,8 +33,6 @@
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
-import java.math.RoundingMode;
-import java.text.NumberFormat;
import java.util.Locale;
import jdk.dynalink.linker.GuardedInvocation;
import jdk.dynalink.linker.LinkRequest;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Wed Jan 06 14:54:24 2016 +0000
@@ -210,14 +210,6 @@
}
@Override
- public Object get(final long key) {
- if (key >= 0 && key < value.length()) {
- return String.valueOf(value.charAt((int)key));
- }
- return super.get(key);
- }
-
- @Override
public Object get(final int key) {
if (key >= 0 && key < value.length()) {
return String.valueOf(value.charAt(key));
@@ -236,36 +228,11 @@
}
@Override
- public int getInt(final long key, final int programPoint) {
- return JSType.toInt32MaybeOptimistic(get(key), programPoint);
- }
-
- @Override
public int getInt(final int key, final int programPoint) {
return JSType.toInt32MaybeOptimistic(get(key), programPoint);
}
@Override
- public long getLong(final Object key, final int programPoint) {
- return JSType.toLongMaybeOptimistic(get(key), programPoint);
- }
-
- @Override
- public long getLong(final double key, final int programPoint) {
- return JSType.toLongMaybeOptimistic(get(key), programPoint);
- }
-
- @Override
- public long getLong(final long key, final int programPoint) {
- return JSType.toLongMaybeOptimistic(get(key), programPoint);
- }
-
- @Override
- public long getLong(final int key, final int programPoint) {
- return JSType.toLongMaybeOptimistic(get(key), programPoint);
- }
-
- @Override
public double getDouble(final Object key, final int programPoint) {
return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@@ -276,11 +243,6 @@
}
@Override
- public double getDouble(final long key, final int programPoint) {
- return JSType.toNumberMaybeOptimistic(get(key), programPoint);
- }
-
- @Override
public double getDouble(final int key, final int programPoint) {
return JSType.toNumberMaybeOptimistic(get(key), programPoint);
}
@@ -298,12 +260,6 @@
}
@Override
- public boolean has(final long key) {
- final int index = ArrayIndex.getArrayIndex(key);
- return isValidStringIndex(index) || super.has(key);
- }
-
- @Override
public boolean has(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
return isValidStringIndex(index) || super.has(key);
@@ -322,12 +278,6 @@
}
@Override
- public boolean hasOwnProperty(final long key) {
- final int index = ArrayIndex.getArrayIndex(key);
- return isValidStringIndex(index) || super.hasOwnProperty(key);
- }
-
- @Override
public boolean hasOwnProperty(final double key) {
final int index = ArrayIndex.getArrayIndex(key);
return isValidStringIndex(index) || super.hasOwnProperty(key);
@@ -339,12 +289,6 @@
}
@Override
- public boolean delete(final long key, final boolean strict) {
- final int index = ArrayIndex.getArrayIndex(key);
- return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
- }
-
- @Override
public boolean delete(final double key, final boolean strict) {
final int index = ArrayIndex.getArrayIndex(key);
return checkDeleteIndex(index, strict)? false : super.delete(key, strict);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -138,16 +138,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -174,11 +164,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -32,6 +32,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;
+import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
import jdk.nashorn.internal.objects.annotations.Function;
@@ -41,6 +42,7 @@
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
@@ -78,7 +80,7 @@
private static final class Uint32ArrayData extends TypedArrayData<IntBuffer> {
- private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", long.class, int.class).methodHandle();
+ private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", double.class, int.class).methodHandle();
private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
private Uint32ArrayData(final IntBuffer nb, final int start, final int end) {
@@ -103,14 +105,18 @@
return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
}
- private long getElem(final int index) {
+ private int getRawElem(final int index) {
try {
- return JSType.toUint32(nb.get(index));
+ return nb.get(index);
} catch (final IndexOutOfBoundsException e) {
throw new ClassCastException(); //force relink - this works for unoptimistic too
}
}
+ private double getElem(final int index) {
+ return JSType.toUint32(getRawElem(index));
+ }
+
private void setElem(final int index, final int elem) {
try {
if (index < nb.limit()) {
@@ -128,42 +134,37 @@
@Override
public Class<?> getElementType() {
- return long.class;
+ return double.class;
}
@Override
public Class<?> getBoxedElementType() {
- return Integer.class;
+ return Double.class;
}
@Override
public int getInt(final int index) {
- return (int)getLong(index);
+ return getRawElem(index);
}
@Override
- public long getLong(final int index) {
+ public int getIntOptimistic(final int index, final int programPoint) {
+ return JSType.toUint32Optimistic(getRawElem(index), programPoint);
+ }
+
+ @Override
+ public double getDouble(final int index) {
return getElem(index);
}
@Override
- public long getLongOptimistic(final int index, final int programPoint) {
+ public double getDoubleOptimistic(final int index, final int programPoint) {
return getElem(index);
}
@Override
- public double getDouble(final int index) {
- return getLong(index);
- }
-
- @Override
- public double getDoubleOptimistic(final int index, final int programPoint) {
- return getLong(index);
- }
-
- @Override
public Object getObject(final int index) {
- return getLong(index);
+ return getElem(index);
}
@Override
@@ -178,11 +179,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java Wed Jan 06 14:54:24 2016 +0000
@@ -138,16 +138,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -174,11 +164,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, (int)value, strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java Wed Jan 06 14:54:24 2016 +0000
@@ -168,16 +168,6 @@
}
@Override
- public long getLong(final int index) {
- return getInt(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return getElem(index);
- }
-
- @Override
public double getDouble(final int index) {
return getInt(index);
}
@@ -204,11 +194,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return set(index, (int)value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return set(index, rint(value), strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Wed Jan 06 14:54:24 2016 +0000
@@ -293,8 +293,6 @@
private static Class<?> getType(final Object value) {
if (value instanceof Integer) {
return int.class;
- } else if (value instanceof Long) {
- return long.class;
} else if (value instanceof Double) {
return double.class;
} else {
@@ -477,8 +475,6 @@
final double d = Double.parseDouble(source.substring(start, pos));
if (JSType.isRepresentableAsInt(d)) {
return (int) d;
- } else if (JSType.isRepresentableAsLong(d)) {
- return (long) d;
}
return d;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Wed Jan 06 14:54:24 2016 +0000
@@ -1131,11 +1131,7 @@
*/
private static Number valueOf(final String valueString, final int radix) throws NumberFormatException {
try {
- final long value = Long.parseLong(valueString, radix);
- if(value >= MIN_INT_L && value <= MAX_INT_L) {
- return (int)value;
- }
- return value;
+ return Integer.parseInt(valueString, radix);
} catch (final NumberFormatException e) {
if (radix == 10) {
return Double.valueOf(valueString);
@@ -1782,8 +1778,6 @@
//yet we don't want e.g. 1e6 to be a double unnecessarily
if (JSType.isStrictlyRepresentableAsInt(value)) {
return (int)value;
- } else if (JSType.isStrictlyRepresentableAsLong(value)) {
- return (long)value;
}
return value;
case STRING:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/AccessorProperty.java Wed Jan 06 14:54:24 2016 +0000
@@ -221,7 +221,7 @@
assert setterType == null || setterType == getterType;
- if (getterType == int.class || getterType == long.class) {
+ if (getterType == int.class) {
primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE);
primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE);
} else if (getterType == double.class) {
@@ -400,17 +400,6 @@
}
}
- @Override
- public long getLongValue(final ScriptObject self, final ScriptObject owner) {
- try {
- return (long)getGetter(long.class).invokeExact((Object)self);
- } catch (final Error | RuntimeException e) {
- throw e;
- } catch (final Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
@Override
public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
try {
@@ -453,21 +442,6 @@
* @param self owner
* @param value value
*/
- protected final void invokeSetter(final ScriptObject self, final long value) {
- try {
- getSetter(long.class, self.getMap()).invokeExact((Object)self, value);
- } catch (final Error | RuntimeException e) {
- throw e;
- } catch (final Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * Invoke setter for this property with a value
- * @param self owner
- * @param value value
- */
protected final void invokeSetter(final ScriptObject self, final double value) {
try {
getSetter(double.class, self.getMap()).invokeExact((Object)self, value);
@@ -500,12 +474,6 @@
}
@Override
- public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) {
- assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
- invokeSetter(self, value);
- }
-
- @Override
public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) {
assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
invokeSetter(self, value);
@@ -533,7 +501,6 @@
final int i = getAccessorTypeIndex(type);
assert type == int.class ||
- type == long.class ||
type == double.class ||
type == Object.class :
"invalid getter type " + type + " for " + getKey();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DebuggerSupport.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DebuggerSupport.java Wed Jan 06 14:54:24 2016 +0000
@@ -239,7 +239,7 @@
if (ScriptObject.isArray(object)) {
sb.append('[');
- final long length = object.getLong("length", INVALID_PROGRAM_POINT);
+ final long length = (long) object.getDouble("length", INVALID_PROGRAM_POINT);
for (long i = 0; i < length; i++) {
if (object.has(i)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java Wed Jan 06 14:54:24 2016 +0000
@@ -44,36 +44,11 @@
}
@Override
- public int getInt(final long key, final int programPoint) {
- return getInt(JSType.toObject(key), programPoint);
- }
-
- @Override
public int getInt(final int key, final int programPoint) {
return getInt(JSType.toObject(key), programPoint);
}
@Override
- public long getLong(final Object key, final int programPoint) {
- return JSType.toLong(get(key));
- }
-
- @Override
- public long getLong(final double key, final int programPoint) {
- return getLong(JSType.toObject(key), programPoint);
- }
-
- @Override
- public long getLong(final long key, final int programPoint) {
- return getLong(JSType.toObject(key), programPoint);
- }
-
- @Override
- public long getLong(final int key, final int programPoint) {
- return getLong(JSType.toObject(key), programPoint);
- }
-
- @Override
public double getDouble(final Object key, final int programPoint) {
return JSType.toNumber(get(key));
}
@@ -84,11 +59,6 @@
}
@Override
- public double getDouble(final long key, final int programPoint) {
- return getDouble(JSType.toObject(key), programPoint);
- }
-
- @Override
public double getDouble(final int key, final int programPoint) {
return getDouble(JSType.toObject(key), programPoint);
}
@@ -102,11 +72,6 @@
}
@Override
- public Object get(final long key) {
- return get(JSType.toObject(key));
- }
-
- @Override
public Object get(final int key) {
return get(JSType.toObject(key));
}
@@ -117,11 +82,6 @@
}
@Override
- public void set(final double key, final long value, final int flags) {
- set(JSType.toObject(key), JSType.toObject(value), flags);
- }
-
- @Override
public void set(final double key, final double value, final int flags) {
set(JSType.toObject(key), JSType.toObject(value), flags);
}
@@ -132,36 +92,11 @@
}
@Override
- public void set(final long key, final int value, final int flags) {
- set(JSType.toObject(key), JSType.toObject(value), flags);
- }
-
- @Override
- public void set(final long key, final long value, final int flags) {
- set(JSType.toObject(key), JSType.toObject(value), flags);
- }
-
- @Override
- public void set(final long key, final double value, final int flags) {
- set(JSType.toObject(key), JSType.toObject(value), flags);
- }
-
- @Override
- public void set(final long key, final Object value, final int flags) {
- set(JSType.toObject(key), value, flags);
- }
-
- @Override
public void set(final int key, final int value, final int flags) {
set(JSType.toObject(key), JSType.toObject(value), flags);
}
@Override
- public void set(final int key, final long value, final int flags) {
- set(JSType.toObject(key), JSType.toObject(value), flags);
- }
-
- @Override
public void set(final int key, final double value, final int flags) {
set(JSType.toObject(key), JSType.toObject(value), flags);
}
@@ -177,11 +112,6 @@
}
@Override
- public void set(final Object key, final long value, final int flags) {
- set(key, JSType.toObject(value), flags);
- }
-
- @Override
public void set(final Object key, final double value, final int flags) {
set(key, JSType.toObject(value), flags);
}
@@ -198,11 +128,6 @@
}
@Override
- public boolean has(final long key) {
- return has(JSType.toObject(key));
- }
-
- @Override
public boolean has(final double key) {
return has(JSType.toObject(key));
}
@@ -213,11 +138,6 @@
}
@Override
- public boolean hasOwnProperty(final long key) {
- return hasOwnProperty(JSType.toObject(key));
- }
-
- @Override
public boolean hasOwnProperty(final double key) {
return hasOwnProperty(JSType.toObject(key));
}
@@ -231,11 +151,6 @@
}
@Override
- public boolean delete(final long key, final boolean strict) {
- return delete(JSType.toObject(key), strict);
- }
-
- @Override
public boolean delete(final double key, final boolean strict) {
return delete(JSType.toObject(key), strict);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java Wed Jan 06 14:54:24 2016 +0000
@@ -36,6 +36,9 @@
*/
final class FinalScriptFunctionData extends ScriptFunctionData {
+ // documentation key for this function, may be null
+ private String docKey;
+
private static final long serialVersionUID = -930632846167768864L;
/**
@@ -73,6 +76,23 @@
}
@Override
+ String getDocumentationKey() {
+ return docKey;
+ }
+
+ @Override
+ void setDocumentationKey(final String docKey) {
+ this.docKey = docKey;
+ }
+
+ @Override
+ String getDocumentation() {
+ String doc = docKey != null?
+ FunctionDocumentation.getDoc(docKey) : null;
+ return doc != null? doc : super.getDocumentation();
+ }
+
+ @Override
protected boolean needsCallee() {
final boolean needsCallee = code.getFirst().needsCallee();
assert allNeedCallee(needsCallee);
@@ -89,11 +109,16 @@
}
@Override
- CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, boolean linkLogicOkay) {
assert isValidCallSite(callSiteType) : callSiteType;
CompiledFunction best = null;
for (final CompiledFunction candidate: code) {
+ if (!linkLogicOkay && candidate.hasLinkLogic()) {
+ // Skip! Version with no link logic is desired, but this one has link logic!
+ continue;
+ }
+
if (!forbidden.contains(candidate) && candidate.betterThanFinal(best, callSiteType)) {
best = candidate;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java Wed Jan 06 14:54:24 2016 +0000
@@ -218,13 +218,6 @@
* Get the property value from self as object.
* @return the property value
*/
- public long getLongValue() {
- return property.getLongValue(getGetterReceiver(), getOwner());
- }
- /**
- * Get the property value from self as object.
- * @return the property value
- */
public double getDoubleValue() {
return property.getDoubleValue(getGetterReceiver(), getOwner());
}
@@ -252,16 +245,6 @@
* @param value the new value
* @param strict strict flag
*/
- public void setValue(final long value, final boolean strict) {
- property.setValue(getSetterReceiver(), getOwner(), value, strict);
- }
-
- /**
- * Set the property value in self.
- *
- * @param value the new value
- * @param strict strict flag
- */
public void setValue(final double value, final boolean strict) {
property.setValue(getSetterReceiver(), getOwner(), value, strict);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FunctionDocumentation.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,51 @@
+/*
+ * 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 jdk.nashorn.internal.runtime;
+
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+/**
+ * Utility class to fetch documentation for built-in functions, constructors.
+ */
+final class FunctionDocumentation {
+ private FunctionDocumentation() {}
+
+ private static final String DOCS_RESOURCE = "jdk.nashorn.internal.runtime.resources.Functions";
+
+ private static final ResourceBundle FUNC_DOCS;
+ static {
+ FUNC_DOCS = ResourceBundle.getBundle(DOCS_RESOURCE, Locale.getDefault());
+ }
+
+ static String getDoc(final String docKey) {
+ try {
+ return FUNC_DOCS.getString(docKey);
+ } catch (final RuntimeException ignored) {
+ return null;
+ }
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalFunctions.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalFunctions.java Wed Jan 06 14:54:24 2016 +0000
@@ -48,9 +48,6 @@
/** ParseInt - identity for ints */
public static final MethodHandle PARSEINT_I = MH.dropArguments(MH.identity(int.class), 0, Object.class);
- /** ParseInt - identity for longs */
- public static final MethodHandle PARSEINT_J = MH.dropArguments(MH.identity(long.class), 0, Object.class);
-
/** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */
public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Jan 06 14:54:24 2016 +0000
@@ -119,14 +119,14 @@
public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class);
/** JavaScript compliant conversion function from int to uint32 */
- public static final Call TO_UINT32_I = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, int.class);
+ public static final Call TO_UINT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Optimistic", int.class, int.class, int.class);
+
+ /** JavaScript compliant conversion function from int to uint32 */
+ public static final Call TO_UINT32_DOUBLE = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32Double", double.class, int.class);
/** JavaScript compliant conversion function from Object to uint32 */
public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
- /** JavaScript compliant conversion function from Object to long with type check */
- public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class);
-
/** JavaScript compliant conversion function from number to uint32 */
public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class);
@@ -172,36 +172,6 @@
/** Negate exact exact wrapper for potentially overflowing integer operations */
public static final Call NEGATE_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class);
- /** Add exact wrapper for potentially overflowing long operations */
- public static final Call ADD_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class);
-
- /** Sub exact wrapper for potentially overflowing long operations */
- public static final Call SUB_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class);
-
- /** Multiply exact wrapper for potentially overflowing long operations */
- public static final Call MUL_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class);
-
- /** Div exact wrapper for potentially integer division that turns into float point */
- public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class);
-
- /** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */
- public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class);
-
- /** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */
- public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class);
-
- /** Mod exact wrapper for potentially integer remainders that turns into float point */
- public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class);
-
- /** Decrement exact wrapper for potentially overflowing long operations */
- public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact", long.class, long.class, int.class);
-
- /** Increment exact wrapper for potentially overflowing long operations */
- public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact", long.class, long.class, int.class);
-
- /** Negate exact exact wrapper for potentially overflowing long operations */
- public static final Call NEGATE_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", long.class, long.class, int.class);
-
/** Method handle to convert a JS Object to a Java array. */
public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
@@ -215,7 +185,6 @@
private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
Arrays.asList(
Type.INT,
- Type.LONG,
Type.NUMBER,
Type.OBJECT));
@@ -223,17 +192,14 @@
public static final int TYPE_UNDEFINED_INDEX = -1;
/** table index for integer type - hard coded so it can be used in switches at compile time */
public static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class);
- /** table index for long type - hard coded so it can be used in switches at compile time */
- public static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class);
/** table index for double type - hard coded so it can be used in switches at compile time */
- public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class);
+ public static final int TYPE_DOUBLE_INDEX = 1; //getAccessorTypeIndex(double.class);
/** table index for object type - hard coded so it can be used in switches at compile time */
- public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class);
+ public static final int TYPE_OBJECT_INDEX = 2; //getAccessorTypeIndex(Object.class);
/** object conversion quickies with JS semantics - used for return value and parameter filter */
public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList(
JSType.TO_INT32.methodHandle(),
- JSType.TO_UINT32.methodHandle(),
JSType.TO_NUMBER.methodHandle(),
null
);
@@ -244,7 +210,6 @@
*/
public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList(
JSType.TO_INT32_OPTIMISTIC.methodHandle(),
- JSType.TO_LONG_OPTIMISTIC.methodHandle(),
JSType.TO_NUMBER_OPTIMISTIC.methodHandle(),
null
);
@@ -256,13 +221,16 @@
/** The value of Undefined cast to a double */
public static final double UNDEFINED_DOUBLE = Double.NaN;
+ // Minimum and maximum range between which every long value can be precisely represented as a double.
+ private static final long MAX_PRECISE_DOUBLE = 1L << 53;
+ private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE;
+
/**
* Method handles for getters that return undefined coerced
* to the appropriate type
*/
public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList(
MH.constant(int.class, UNDEFINED_INT),
- MH.constant(long.class, UNDEFINED_LONG),
MH.constant(double.class, UNDEFINED_DOUBLE),
MH.constant(Object.class, Undefined.getUndefined())
);
@@ -428,7 +396,7 @@
/**
* Returns true if double number can be represented as a long. Note that it returns true for negative
- * zero. If you need to exclude negative zero, use {@link #isStrictlyRepresentableAsLong(double)}.
+ * zero.
*
* @param number a double to inspect
* @return true for long representable doubles
@@ -438,29 +406,12 @@
}
/**
- * Returns true if double number can be represented as a long. Note that it returns false for negative
- * zero. If you don't need to distinguish negative zero, use {@link #isRepresentableAsLong(double)}.
- *
- * @param number a double to inspect
- *
- * @return true for long representable doubles
+ * Returns true if long number can be represented as double without loss of precision.
+ * @param number a long number
+ * @return true if the double representation does not lose precision
*/
- public static boolean isStrictlyRepresentableAsLong(final double number) {
- return isRepresentableAsLong(number) && isNotNegativeZero(number);
- }
-
- /**
- * Returns true if Object can be represented as a long
- *
- * @param obj an object to inspect
- *
- * @return true for long representable objects
- */
- public static boolean isRepresentableAsLong(final Object obj) {
- if (obj instanceof Number) {
- return isRepresentableAsLong(((Number)obj).doubleValue());
- }
- return false;
+ public static boolean isRepresentableAsDouble(final long number) {
+ return MAX_PRECISE_DOUBLE >= number && number >= MIN_PRECISE_DOUBLE;
}
/**
@@ -650,22 +601,6 @@
}
/**
- * Check whether a string is representable as a JavaScript number
- *
- * @param str a string
- *
- * @return true if string can be represented as a number
- */
- public static boolean isNumber(final String str) {
- try {
- Double.parseDouble(str);
- return true;
- } catch (final NumberFormatException e) {
- return false;
- }
- }
-
- /**
* Returns true if object represents a primitive JavaScript string value.
* @param obj the object
* @return true if the object represents a primitive JavaScript string value.
@@ -1033,35 +968,6 @@
}
/**
- * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object
- *
- * @param obj object to convert
- * @param programPoint program point
- * @return long
- */
- public static long toLongOptimistic(final Object obj, final int programPoint) {
- if (obj != null) {
- final Class<?> clz = obj.getClass();
- if (clz == Long.class || clz == Integer.class) {
- return ((Number)obj).longValue();
- }
- }
- throw new UnwarrantedOptimismException(obj, programPoint);
- }
-
- /**
- * Object to int conversion that delegates to either {@link #toLong(Object)} or to
- * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not.
- * @param obj the object to convert
- * @param programPoint the program point; can be invalid.
- * @return the value converted to long
- * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid.
- */
- public static long toLongMaybeOptimistic(final Object obj, final int programPoint) {
- return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj);
- }
-
- /**
* JavaScript compliant Object to int32 conversion
* See ECMA 9.5 ToInt32
*
@@ -1098,10 +1004,6 @@
return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj);
}
- // Minimum and maximum range between which every long value can be precisely represented as a double.
- private static final long MAX_PRECISE_DOUBLE = 1L << 53;
- private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE;
-
/**
* JavaScript compliant long to int32 conversion
*
@@ -1154,6 +1056,29 @@
}
/**
+ * Optimistic JavaScript compliant int to uint32 conversion
+ * @param num an int
+ * @param pp the program point
+ * @return the uint32 value if it can be represented by an int
+ * @throws UnwarrantedOptimismException if uint32 value cannot be represented by an int
+ */
+ public static int toUint32Optimistic(final int num, final int pp) {
+ if (num >= 0) {
+ return num;
+ }
+ throw new UnwarrantedOptimismException(toUint32Double(num), pp, Type.NUMBER);
+ }
+
+ /**
+ * JavaScript compliant int to uint32 conversion with double return type
+ * @param num an int
+ * @return the uint32 value as double
+ */
+ public static double toUint32Double(final int num) {
+ return (double) toUint32(num);
+ }
+
+ /**
* JavaScript compliant Object to uint16 conversion
* ECMA 9.7 ToUint16: (Unsigned 16 Bit Integer)
*
@@ -1484,26 +1409,6 @@
try {
return Math.addExact(x, y);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((long)x + (long)y, programPoint);
- }
- }
-
- /**
- * Wrapper for addExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x first term
- * @param y second term
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return Math.addExact(x, y);
- } catch (final ArithmeticException e) {
throw new UnwarrantedOptimismException((double)x + (double)y, programPoint);
}
}
@@ -1524,26 +1429,6 @@
try {
return Math.subtractExact(x, y);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((long)x - (long)y, programPoint);
- }
- }
-
- /**
- * Wrapper for subExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x first term
- * @param y second term
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return Math.subtractExact(x, y);
- } catch (final ArithmeticException e) {
throw new UnwarrantedOptimismException((double)x - (double)y, programPoint);
}
}
@@ -1564,26 +1449,6 @@
try {
return Math.multiplyExact(x, y);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((long)x * (long)y, programPoint);
- }
- }
-
- /**
- * Wrapper for mulExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x first term
- * @param y second term
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return Math.multiplyExact(x, y);
- } catch (final ArithmeticException e) {
throw new UnwarrantedOptimismException((double)x * (double)y, programPoint);
}
}
@@ -1655,71 +1520,6 @@
}
/**
- * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as
- * long.
- *
- * @param x first term
- * @param y second term
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if the result of the division can't be represented as long.
- */
- public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
- final long res;
- try {
- res = x / y;
- } catch (final ArithmeticException e) {
- assert y == 0L; // Only div by zero anticipated
- throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint);
- }
- final long rem = x % y;
- if (rem == 0L) {
- return res;
- }
- throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
- }
-
- /**
- * Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs
- * is coerced to long.
- * @param x the dividend
- * @param y the divisor
- * @return the result
- */
- public static long divZero(final long x, final long y) {
- return y == 0L ? 0L : x / y;
- }
-
- /**
- * Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs
- * is coerced to long.
- * @param x the dividend
- * @param y the divisor
- * @return the remainder
- */
- public static long remZero(final long x, final long y) {
- return y == 0L ? 0L : x % y;
- }
-
- /**
- * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
- *
- * @param x first term
- * @param y second term
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if the modulo can't be represented as int.
- */
- public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return x % y;
- } catch (final ArithmeticException e) {
- assert y == 0L; // Only mod by zero anticipated
- throw new UnwarrantedOptimismException(Double.NaN, programPoint);
- }
- }
-
- /**
* Wrapper for decrementExact
*
* Catches ArithmeticException and rethrows as UnwarrantedOptimismException
@@ -1734,26 +1534,7 @@
try {
return Math.decrementExact(x);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((long)x - 1, programPoint);
- }
- }
-
- /**
- * Wrapper for decrementExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x number to negate
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return Math.decrementExact(x);
- } catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((double)x - 1L, programPoint);
+ throw new UnwarrantedOptimismException((double)x - 1, programPoint);
}
}
@@ -1772,26 +1553,7 @@
try {
return Math.incrementExact(x);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((long)x + 1, programPoint);
- }
- }
-
- /**
- * Wrapper for incrementExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x the number to increment
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
- try {
- return Math.incrementExact(x);
- } catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException((double)x + 1L, programPoint);
+ throw new UnwarrantedOptimismException((double)x + 1, programPoint);
}
}
@@ -1813,28 +1575,6 @@
}
return Math.negateExact(x);
} catch (final ArithmeticException e) {
- throw new UnwarrantedOptimismException(-(long)x, programPoint);
- }
- }
-
- /**
- * Wrapper for negateExact
- *
- * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
- * containing the result and the program point of the failure
- *
- * @param x the number to negate
- * @param programPoint program point id
- * @return the result
- * @throws UnwarrantedOptimismException if overflow occurs
- */
- public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
- try {
- if (x == 0L) {
- throw new UnwarrantedOptimismException(-0.0, programPoint);
- }
- return Math.negateExact(x);
- } catch (final ArithmeticException e) {
throw new UnwarrantedOptimismException(-(double)x, programPoint);
}
}
@@ -1866,8 +1606,6 @@
return TYPE_UNDEFINED_INDEX;
} else if (type == int.class) {
return TYPE_INT_INDEX;
- } else if (type == long.class) {
- return TYPE_LONG_INDEX;
} else if (type == double.class) {
return TYPE_DOUBLE_INDEX;
} else if (!type.isPrimitive()) {
@@ -1972,8 +1710,6 @@
public static Class<?> getBoxedClass(final Class<?> clazz) {
if (clazz == int.class) {
return Integer.class;
- } else if (clazz == long.class) {
- return Long.class;
} else if (clazz == double.class) {
return Double.class;
}
@@ -1991,8 +1727,6 @@
if (o != null) {
if (o.getClass() == Integer.class) {
return MH.constant(int.class, ((Integer)o));
- } else if (o.getClass() == Long.class) {
- return MH.constant(long.class, ((Long)o));
} else if (o.getClass() == Double.class) {
return MH.constant(double.class, ((Double)o));
}
@@ -2010,8 +1744,6 @@
return Object.class;
} else if (o.getClass() == Integer.class) {
return int.class;
- } else if (o.getClass() == Long.class) {
- return long.class;
} else if (o.getClass() == Double.class) {
return double.class;
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Jan 06 14:54:24 2016 +0000
@@ -43,52 +43,42 @@
*/
public final class OptimisticReturnFilters {
private static final MethodHandle[] ENSURE_INT;
- private static final MethodHandle[] ENSURE_LONG;
private static final MethodHandle[] ENSURE_NUMBER;
+ // These extend the type index constants in JSType
+ private static final int VOID_TYPE_INDEX;
private static final int BOOLEAN_TYPE_INDEX;
private static final int CHAR_TYPE_INDEX;
+ private static final int LONG_TYPE_INDEX;
private static final int FLOAT_TYPE_INDEX;
- private static final int VOID_TYPE_INDEX;
static {
final MethodHandle INT_DOUBLE = findOwnMH("ensureInt", int.class, double.class, int.class);
ENSURE_INT = new MethodHandle[] {
null,
- findOwnMH("ensureInt", int.class, long.class, int.class),
INT_DOUBLE,
findOwnMH("ensureInt", int.class, Object.class, int.class),
findOwnMH("ensureInt", int.class, int.class),
findOwnMH("ensureInt", int.class, boolean.class, int.class),
findOwnMH("ensureInt", int.class, char.class, int.class),
+ findOwnMH("ensureInt", int.class, long.class, int.class),
INT_DOUBLE.asType(INT_DOUBLE.type().changeParameterType(0, float.class)),
};
- VOID_TYPE_INDEX = ENSURE_INT.length - 4;
- BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 3;
- CHAR_TYPE_INDEX = ENSURE_INT.length - 2;
+ VOID_TYPE_INDEX = ENSURE_INT.length - 5;
+ BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 4;
+ CHAR_TYPE_INDEX = ENSURE_INT.length - 3;
+ LONG_TYPE_INDEX = ENSURE_INT.length - 2;
FLOAT_TYPE_INDEX = ENSURE_INT.length - 1;
- final MethodHandle LONG_DOUBLE = findOwnMH("ensureLong", long.class, double.class, int.class);
- ENSURE_LONG = new MethodHandle[] {
- null,
- null,
- LONG_DOUBLE,
- findOwnMH("ensureLong", long.class, Object.class, int.class),
- ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(long.class)),
- ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(long.class)),
- ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(long.class)),
- LONG_DOUBLE.asType(LONG_DOUBLE.type().changeParameterType(0, float.class)),
- };
-
ENSURE_NUMBER = new MethodHandle[] {
null,
null,
- null,
findOwnMH("ensureNumber", double.class, Object.class, int.class),
ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(double.class)),
ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(double.class)),
ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(double.class)),
+ findOwnMH("ensureNumber", double.class, long.class, int.class),
null
};
}
@@ -136,8 +126,6 @@
final int provableTypeIndex = getProvableTypeIndex(provable);
if (actual == int.class) {
guard = ENSURE_INT[provableTypeIndex];
- } else if (actual == long.class) {
- guard = ENSURE_LONG[provableTypeIndex];
} else if (actual == double.class) {
guard = ENSURE_NUMBER[provableTypeIndex];
} else {
@@ -167,6 +155,8 @@
return 0; // never needs a guard, as it's assignable to int
} else if(provable == char.class) {
return CHAR_TYPE_INDEX;
+ } else if(provable == long.class) {
+ return LONG_TYPE_INDEX;
} else if(provable == float.class) {
return FLOAT_TYPE_INDEX;
}
@@ -179,7 +169,7 @@
if (JSType.isRepresentableAsInt(arg)) {
return (int)arg;
}
- throw new UnwarrantedOptimismException(arg, programPoint);
+ throw UnwarrantedOptimismException.createNarrowest(arg, programPoint);
}
@SuppressWarnings("unused")
@@ -187,7 +177,7 @@
if (JSType.isStrictlyRepresentableAsInt(arg)) {
return (int)arg;
}
- throw new UnwarrantedOptimismException(arg, programPoint);
+ throw new UnwarrantedOptimismException(arg, programPoint, Type.NUMBER);
}
/**
@@ -210,7 +200,7 @@
return (int)d;
}
}
- throw new UnwarrantedOptimismException(arg, programPoint);
+ throw UnwarrantedOptimismException.createNarrowest(arg, programPoint);
}
private static boolean isPrimitiveNumberWrapper(final Object obj) {
@@ -238,51 +228,30 @@
throw new UnwarrantedOptimismException(ScriptRuntime.UNDEFINED, programPoint, Type.OBJECT);
}
- private static long ensureLong(final double arg, final int programPoint) {
- if (JSType.isStrictlyRepresentableAsLong(arg)) {
- return (long)arg;
+
+ @SuppressWarnings("unused")
+ private static double ensureNumber(final long arg, final int programPoint) {
+ if (JSType.isRepresentableAsDouble(arg)) {
+ return (double) arg;
}
- throw new UnwarrantedOptimismException(arg, programPoint);
+ throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
}
/**
- * Returns the argument value as a long. If the argument is not a wrapper for a primitive numeric type
- * with a value that can be exactly represented as a long, throw an {@link UnwarrantedOptimismException}.
- * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_LONG}.
- * @param arg the original argument.
- * @param programPoint the program point used in the exception
- * @return the value of the argument as a long.
- * @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type with
- * a value that can be exactly represented as a long
- */
- public static long ensureLong(final Object arg, final int programPoint) {
- if (arg != null) {
- final Class<?> c = arg.getClass();
- if (c == Long.class) {
- // Must check for Long separately, as Long.doubleValue() isn't precise.
- return ((Long)arg);
- } else if (c == Integer.class || c == Double.class || c == Float.class || c == Short.class ||
- c == Byte.class) {
- return ensureLong(((Number)arg).doubleValue(), programPoint);
- }
- }
- throw new UnwarrantedOptimismException(arg, programPoint);
- }
-
- /**
- * Returns the argument value as a double. If the argument is not a a wrapper for a primitive numeric type
- * throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
- * can use it. See {code CodeGenerator.ENSURE_NUMBER}.
+ * Returns the argument value as a double. If the argument is not a wrapper for a primitive numeric type
+ * that can be represented as double throw an {@link UnwarrantedOptimismException}.
+ * This method is only public so that generated script code can use it. See {code CodeGenerator.ENSURE_NUMBER}.
* @param arg the original argument.
* @param programPoint the program point used in the exception
* @return the value of the argument as a double.
* @throws UnwarrantedOptimismException if the argument is not a wrapper for a primitive numeric type.
*/
public static double ensureNumber(final Object arg, final int programPoint) {
- if (isPrimitiveNumberWrapper(arg)) {
- return ((Number)arg).doubleValue();
+ if (isPrimitiveNumberWrapper(arg)
+ && (arg.getClass() != Long.class || JSType.isRepresentableAsDouble((Long) arg))) {
+ return ((Number) arg).doubleValue();
}
- throw new UnwarrantedOptimismException(arg, programPoint);
+ throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
}
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Property.java Wed Jan 06 14:54:24 2016 +0000
@@ -450,16 +450,6 @@
* @param owner the owner of the property
* @return the property value
*/
- public abstract long getLongValue(final ScriptObject self, final ScriptObject owner);
-
- /**
- * get the Object value of this property from {@code owner}. This allows to bypass creation of the
- * getter MethodHandle for spill and user accessor properties.
- *
- * @param self the this object
- * @param owner the owner of the property
- * @return the property value
- */
public abstract double getDoubleValue(final ScriptObject self, final ScriptObject owner);
/**
@@ -492,17 +482,6 @@
* @param value the new property value
* @param strict is this a strict setter?
*/
- public abstract void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict);
-
- /**
- * Set the value of this property in {@code owner}. This allows to bypass creation of the
- * setter MethodHandle for spill and user accessor properties.
- *
- * @param self the this object
- * @param owner the owner object
- * @param value the new property value
- * @param strict is this a strict setter?
- */
public abstract void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict);
/**
@@ -593,8 +572,6 @@
return "undef";
} else if (type == int.class) {
return "i";
- } else if (type == long.class) {
- return "j";
} else if (type == double.class) {
return "d";
} else {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyAccess.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyAccess.java Wed Jan 06 14:54:24 2016 +0000
@@ -57,49 +57,9 @@
* @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public int getInt(long key, int programPoint);
-
- /**
- * Get the value for a given key and return it as an int
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
public int getInt(int key, int programPoint);
/**
- * Get the value for a given key and return it as a long
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
- public long getLong(Object key, int programPoint);
-
- /**
- * Get the value for a given key and return it as a long
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
- public long getLong(double key, int programPoint);
-
- /**
- * Get the value for a given key and return it as a long
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
- public long getLong(long key, int programPoint);
-
- /**
- * Get the value for a given key and return it as a long
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
- public long getLong(int key, int programPoint);
-
- /**
* Get the value for a given key and return it as a double
* @param key the key
* @param programPoint or INVALID_PROGRAM_POINT if pessimistic
@@ -121,14 +81,6 @@
* @param programPoint or INVALID_PROGRAM_POINT if pessimistic
* @return the value
*/
- public double getDouble(long key, int programPoint);
-
- /**
- * Get the value for a given key and return it as a double
- * @param key the key
- * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
- * @return the value
- */
public double getDouble(int key, int programPoint);
/**
@@ -150,13 +102,6 @@
* @param key the key
* @return the value
*/
- public Object get(long key);
-
- /**
- * Get the value for a given key and return it as an Object
- * @param key the key
- * @return the value
- */
public Object get(int key);
/**
@@ -173,14 +118,6 @@
* @param value the value
* @param flags call site flags
*/
- public void set(Object key, long value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
public void set(Object key, double value, int flags);
/**
@@ -205,14 +142,6 @@
* @param value the value
* @param flags call site flags
*/
- public void set(double key, long value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
public void set(double key, double value, int flags);
/**
@@ -229,38 +158,6 @@
* @param value the value
* @param flags call site flags
*/
- public void set(long key, int value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
- public void set(long key, long value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
- public void set(long key, double value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
- public void set(long key, Object value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
public void set(int key, int value, int flags);
/**
@@ -269,14 +166,6 @@
* @param value the value
* @param flags call site flags
*/
- public void set(int key, long value, int flags);
-
- /**
- * Set the value of a given key
- * @param key the key
- * @param value the value
- * @param flags call site flags
- */
public void set(int key, double value, int flags);
/**
@@ -306,13 +195,6 @@
* @param key the key
* @return true if key exists
*/
- public boolean has(long key);
-
- /**
- * Check if the given key exists anywhere in the proto chain
- * @param key the key
- * @return true if key exists
- */
public boolean has(double key);
/**
@@ -334,13 +216,6 @@
* @param key the key
* @return true if key exists
*/
- public boolean hasOwnProperty(long key);
-
- /**
- * Check if the given key exists directly in the implementor
- * @param key the key
- * @return true if key exists
- */
public boolean hasOwnProperty(double key);
/**
@@ -357,14 +232,6 @@
* @param strict are we in strict mode
* @return true if deletion succeeded, false otherwise
*/
- public boolean delete(long key, boolean strict);
-
- /**
- * Delete a property with the given key from the implementor
- * @param key the key
- * @param strict are we in strict mode
- * @return true if deletion succeeded, false otherwise
- */
public boolean delete(double key, boolean strict);
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java Wed Jan 06 14:54:24 2016 +0000
@@ -886,7 +886,7 @@
}
@Override
- synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, final boolean linkLogicOkay) {
assert isValidCallSite(callSiteType) : callSiteType;
CompiledFunction existingBest = pickFunction(callSiteType, false);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Jan 06 14:54:24 2016 +0000
@@ -646,6 +646,33 @@
}
/**
+ * Get the documentation for this function
+ *
+ * @return the documentation
+ */
+ public final String getDocumentation() {
+ return data.getDocumentation();
+ }
+
+ /**
+ * Get the documentation key for this function
+ *
+ * @return the documentation key
+ */
+ public final String getDocumentationKey() {
+ return data.getDocumentationKey();
+ }
+
+ /**
+ * Set the documentation key for this function
+ *
+ * @param docKey documentation key String for this function
+ */
+ public final void setDocumentationKey(final String docKey) {
+ data.setDocumentationKey(docKey);
+ }
+
+ /**
* Get the name for this function
*
* @return the name
@@ -954,6 +981,13 @@
}
}
+ // Is this an unstable callsite which was earlier apply-to-call optimized?
+ // If so, earlier apply2call would have exploded arguments. We have to convert
+ // that as an array again!
+ if (isUnstable && NashornCallSiteDescriptor.isApplyToCall(desc)) {
+ boundHandle = MH.asCollector(boundHandle, Object[].class, type.parameterCount() - 2);
+ }
+
boundHandle = pairArguments(boundHandle, type);
if (bestInvoker.getSwitchPoints() != null) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunctionData.java Wed Jan 06 14:54:24 2016 +0000
@@ -118,6 +118,14 @@
return arity;
}
+ String getDocumentation() {
+ return toSource();
+ }
+
+ String getDocumentationKey() {
+ return null;
+ }
+
final boolean isVariableArity() {
return (flags & IS_VARIABLE_ARITY) != 0;
}
@@ -137,6 +145,15 @@
this.arity = arity;
}
+ /**
+ * Used from nasgen generated code.
+ *
+ * @param doc documentation for this function
+ */
+ void setDocumentationKey(final String docKey) {
+ }
+
+
CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args);
@@ -357,9 +374,23 @@
* @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
* optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
* scope is not known, but that might cause compilation of code that will need more deoptimization passes.
+ * @param linkLogicOkay is a CompiledFunction with a LinkLogic acceptable?
* @return the best function for the specified call site type.
*/
- abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden);
+ abstract CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden, final boolean linkLogicOkay);
+
+ /**
+ * Returns the best function for the specified call site type.
+ * @param callSiteType The call site type. Call site types are expected to have the form
+ * {@code (callee, this[, args...])}.
+ * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
+ * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
+ * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
+ * @return the best function for the specified call site type.
+ */
+ final CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection<CompiledFunction> forbidden) {
+ return getBest(callSiteType, runtimeScope, forbidden, true);
+ }
boolean isValidCallSite(final MethodType callSiteType) {
return callSiteType.parameterCount() >= 2 && // Must have at least (callee, this)
@@ -367,7 +398,7 @@
}
CompiledFunction getGeneric(final ScriptObject runtimeScope) {
- return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS);
+ return getBest(getGenericType(), runtimeScope, CompiledFunction.NO_FUNCTIONS, false);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jan 06 14:54:24 2016 +0000
@@ -33,7 +33,6 @@
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
-import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
@@ -188,7 +187,6 @@
static final MethodHandle[] SET_SLOW = new MethodHandle[] {
findOwnMH_V("set", void.class, Object.class, int.class, int.class),
- findOwnMH_V("set", void.class, Object.class, long.class, int.class),
findOwnMH_V("set", void.class, Object.class, double.class, int.class),
findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
};
@@ -1087,21 +1085,6 @@
return UNDEFINED_INT;
}
- private static long getLongValue(final FindProperty find, final int programPoint) {
- final MethodHandle getter = find.getGetter(long.class, programPoint, null);
- if (getter != null) {
- try {
- return (long)getter.invokeExact((Object)find.getGetterReceiver());
- } catch (final Error|RuntimeException e) {
- throw e;
- } catch (final Throwable e) {
- throw new RuntimeException(e);
- }
- }
-
- return UNDEFINED_LONG;
- }
-
private static double getDoubleValue(final FindProperty find, final int programPoint) {
final MethodHandle getter = find.getGetter(double.class, programPoint, null);
if (getter != null) {
@@ -2804,18 +2787,6 @@
}
@Override
- public int getInt(final long key, final int programPoint) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
- }
-
- return getInt(index, JSType.toString(key), programPoint);
- }
-
- @Override
public int getInt(final int key, final int programPoint) {
final int index = getArrayIndex(key);
final ArrayData array = getArray();
@@ -2827,88 +2798,6 @@
return getInt(index, JSType.toString(key), programPoint);
}
- private long getLong(final int index, final Object key, final int programPoint) {
- if (isValidArrayIndex(index)) {
- for (ScriptObject object = this; ; ) {
- if (object.getMap().containsArrayKeys()) {
- final FindProperty find = object.findProperty(key, false, this);
- if (find != null) {
- return getLongValue(find, programPoint);
- }
- }
-
- if ((object = object.getProto()) == null) {
- break;
- }
-
- final ArrayData array = object.getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ?
- array.getLongOptimistic(index, programPoint) :
- array.getLong(index);
- }
- }
- } else {
- final FindProperty find = findProperty(key, true);
-
- if (find != null) {
- return getLongValue(find, programPoint);
- }
- }
-
- return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
- }
-
- @Override
- public long getLong(final Object key, final int programPoint) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
- }
-
- return getLong(index, JSType.toPropertyKey(primitiveKey), programPoint);
- }
-
- @Override
- public long getLong(final double key, final int programPoint) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
- }
-
- return getLong(index, JSType.toString(key), programPoint);
- }
-
- @Override
- public long getLong(final long key, final int programPoint) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
- }
-
- return getLong(index, JSType.toString(key), programPoint);
- }
-
- @Override
- public long getLong(final int key, final int programPoint) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key);
- }
-
- return getLong(index, JSType.toString(key), programPoint);
- }
-
private double getDouble(final int index, final Object key, final int programPoint) {
if (isValidArrayIndex(index)) {
for (ScriptObject object = this; ; ) {
@@ -2968,18 +2857,6 @@
}
@Override
- public double getDouble(final long key, final int programPoint) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
- }
-
- return getDouble(index, JSType.toString(key), programPoint);
- }
-
- @Override
public double getDouble(final int key, final int programPoint) {
final int index = getArrayIndex(key);
final ArrayData array = getArray();
@@ -3049,18 +2926,6 @@
}
@Override
- public Object get(final long key) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- return array.getObject(index);
- }
-
- return get(index, JSType.toString(key));
- }
-
- @Override
public Object get(final int key) {
final int index = getArrayIndex(key);
final ArrayData array = getArray();
@@ -3143,15 +3008,6 @@
}
}
- private void doesNotHave(final int index, final long value, final int callSiteFlags) {
- final long oldLength = getArray().length();
- final long longIndex = ArrayIndex.toLongIndex(index);
- if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
- final boolean strict = isStrictFlag(callSiteFlags);
- setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
- }
- }
-
private void doesNotHave(final int index, final double value, final int callSiteFlags) {
final long oldLength = getArray().length();
final long longIndex = ArrayIndex.toLongIndex(index);
@@ -3258,26 +3114,6 @@
}
@Override
- public void set(final Object key, final long value, final int callSiteFlags) {
- final Object primitiveKey = JSType.toPrimitive(key, String.class);
- final int index = getArrayIndex(primitiveKey);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final Object propName = JSType.toPropertyKey(primitiveKey);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
public void set(final Object key, final double value, final int callSiteFlags) {
final Object primitiveKey = JSType.toPrimitive(key, String.class);
final int index = getArrayIndex(primitiveKey);
@@ -3337,25 +3173,6 @@
}
@Override
- public void set(final double key, final long value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
public void set(final double key, final double value, final int callSiteFlags) {
final int index = getArrayIndex(key);
@@ -3394,82 +3211,6 @@
}
@Override
- public void set(final long key, final int value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
- public void set(final long key, final long value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
- public void set(final long key, final double value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
- public void set(final long key, final Object value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, value);
- }
-
- @Override
public void set(final int key, final int value, final int callSiteFlags) {
final int index = getArrayIndex(key);
if (isValidArrayIndex(index)) {
@@ -3487,25 +3228,6 @@
}
@Override
- public void set(final int key, final long value, final int callSiteFlags) {
- final int index = getArrayIndex(key);
-
- if (isValidArrayIndex(index)) {
- final ArrayData data = getArray();
- if (data.has(index)) {
- setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
- } else {
- doesNotHave(index, value, callSiteFlags);
- }
-
- return;
- }
-
- final String propName = JSType.toString(key);
- setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
- }
-
- @Override
public void set(final int key, final double value, final int callSiteFlags) {
final int index = getArrayIndex(key);
@@ -3557,12 +3279,6 @@
}
@Override
- public boolean has(final long key) {
- final int index = getArrayIndex(key);
- return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
- }
-
- @Override
public boolean has(final int key) {
final int index = getArrayIndex(key);
return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
@@ -3595,12 +3311,6 @@
}
@Override
- public boolean hasOwnProperty(final long key) {
- final int index = getArrayIndex(key);
- return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
- }
-
- @Override
public boolean hasOwnProperty(final double key) {
final int index = getArrayIndex(key);
return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
@@ -3626,22 +3336,6 @@
}
@Override
- public boolean delete(final long key, final boolean strict) {
- final int index = getArrayIndex(key);
- final ArrayData array = getArray();
-
- if (array.has(index)) {
- if (array.canDelete(index, strict)) {
- setArray(array.delete(index));
- return true;
- }
- return false;
- }
-
- return deleteObject(JSType.toObject(key), strict);
- }
-
- @Override
public boolean delete(final double key, final boolean strict) {
final int index = getArrayIndex(key);
final ArrayData array = getArray();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java Wed Jan 06 14:54:24 2016 +0000
@@ -278,9 +278,8 @@
* @param str a {@link String} to tokenize.
* @return a {@link List} of {@link String}s representing the tokens that
* constitute the string.
- * @throws IOException in case {@link StreamTokenizer#nextToken()} raises it.
*/
- public static List<String> tokenizeString(final String str) throws IOException {
+ public static List<String> tokenizeString(final String str) {
final StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(str));
tokenizer.resetSyntax();
tokenizer.wordChars(0, 255);
@@ -290,7 +289,7 @@
tokenizer.quoteChar('\'');
final List<String> tokenList = new ArrayList<>();
final StringBuilder toAppend = new StringBuilder();
- while (tokenizer.nextToken() != StreamTokenizer.TT_EOF) {
+ while (nextToken(tokenizer) != StreamTokenizer.TT_EOF) {
final String s = tokenizer.sval;
// The tokenizer understands about honoring quoted strings and recognizes
// them as one token that possibly contains multiple space-separated words.
@@ -309,4 +308,12 @@
}
return tokenList;
}
+
+ private static int nextToken(final StreamTokenizer tokenizer) {
+ try {
+ return tokenizer.nextToken();
+ } catch (final IOException ioe) {
+ return StreamTokenizer.TT_EOF;
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java Wed Jan 06 14:54:24 2016 +0000
@@ -49,7 +49,10 @@
private final Type returnType;
/**
- * Constructor
+ * Constructor without explicit return type. The return type is determined statically from the class of
+ * the return value, and only canonical internal number representations are recognized. Use
+ * {@link #createNarrowest} if you want to handle float and long values as numbers instead of objects.
+ *
* @param returnValue actual return value from the too narrow operation
* @param programPoint program point where unwarranted optimism was detected
*/
@@ -58,7 +61,7 @@
}
/**
- * Check if a program point is valid
+ * Check if a program point is valid.
* @param programPoint the program point
* @return true if valid
*/
@@ -70,8 +73,6 @@
private static Type getReturnType(final Object v) {
if (v instanceof Double) {
return Type.NUMBER;
- } else if (v instanceof Long) {
- return Type.LONG;
}
assert !(v instanceof Integer) : v + " is an int"; // Can't have an unwarranted optimism exception with int
return Type.OBJECT;
@@ -97,6 +98,22 @@
}
/**
+ * Create an {@code UnwarrantedOptimismException} with the given return value and program point, narrowing
+ * the type to {@code number} if the value is a float or a long that can be represented as double.
+ *
+ * @param returnValue the return value
+ * @param programPoint the program point
+ * @return the exception
+ */
+ public static UnwarrantedOptimismException createNarrowest(final Object returnValue, final int programPoint) {
+ if (returnValue instanceof Float
+ || (returnValue instanceof Long && JSType.isRepresentableAsDouble((Long) returnValue))) {
+ return new UnwarrantedOptimismException(((Number) returnValue).doubleValue(), programPoint, Type.NUMBER);
+ }
+ return new UnwarrantedOptimismException(returnValue, programPoint);
+ }
+
+ /**
* Get the return value. This is a destructive readout, after the method is invoked the return value is null'd out.
* @return return value
*/
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/UserAccessorProperty.java Wed Jan 06 14:54:24 2016 +0000
@@ -71,13 +71,11 @@
/** Getter method handle */
private final static MethodHandle INVOKE_OBJECT_GETTER = findOwnMH_S("invokeObjectGetter", Object.class, Accessors.class, MethodHandle.class, Object.class);
private final static MethodHandle INVOKE_INT_GETTER = findOwnMH_S("invokeIntGetter", int.class, Accessors.class, MethodHandle.class, int.class, Object.class);
- private final static MethodHandle INVOKE_LONG_GETTER = findOwnMH_S("invokeLongGetter", long.class, Accessors.class, MethodHandle.class, int.class, Object.class);
private final static MethodHandle INVOKE_NUMBER_GETTER = findOwnMH_S("invokeNumberGetter", double.class, Accessors.class, MethodHandle.class, int.class, Object.class);
/** Setter method handle */
private final static MethodHandle INVOKE_OBJECT_SETTER = findOwnMH_S("invokeObjectSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, Object.class);
private final static MethodHandle INVOKE_INT_SETTER = findOwnMH_S("invokeIntSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, int.class);
- private final static MethodHandle INVOKE_LONG_SETTER = findOwnMH_S("invokeLongSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, long.class);
private final static MethodHandle INVOKE_NUMBER_SETTER = findOwnMH_S("invokeNumberSetter", void.class, Accessors.class, MethodHandle.class, String.class, Object.class, double.class);
private static final Object OBJECT_GETTER_INVOKER_KEY = new Object();
@@ -188,11 +186,6 @@
}
@Override
- public long getLongValue(final ScriptObject self, final ScriptObject owner) {
- return (long)getObjectValue(self, owner);
- }
-
- @Override
public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
return (double)getObjectValue(self, owner);
}
@@ -214,11 +207,6 @@
}
@Override
- public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) {
- setValue(self, owner, (Object) value, strict);
- }
-
- @Override
public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) {
setValue(self, owner, (Object) value, strict);
}
@@ -244,8 +232,6 @@
public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
if (type == int.class) {
return INVOKE_INT_GETTER;
- } else if (type == long.class) {
- return INVOKE_LONG_GETTER;
} else if (type == double.class) {
return INVOKE_NUMBER_GETTER;
} else {
@@ -269,8 +255,6 @@
public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
if (type == int.class) {
return INVOKE_INT_SETTER;
- } else if (type == long.class) {
- return INVOKE_LONG_SETTER;
} else if (type == double.class) {
return INVOKE_NUMBER_SETTER;
} else {
@@ -320,16 +304,6 @@
}
@SuppressWarnings("unused")
- private static long invokeLongGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
- final Object func = gs.getter;
- if (func instanceof ScriptFunction) {
- return (long) invoker.invokeExact(func, self);
- }
-
- throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
- }
-
- @SuppressWarnings("unused")
private static double invokeNumberGetter(final Accessors gs, final MethodHandle invoker, final int programPoint, final Object self) throws Throwable {
final Object func = gs.getter;
if (func instanceof ScriptFunction) {
@@ -360,16 +334,6 @@
}
@SuppressWarnings("unused")
- private static void invokeLongSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final long value) throws Throwable {
- final Object func = gs.setter;
- if (func instanceof ScriptFunction) {
- invoker.invokeExact(func, self, value);
- } else if (name != null) {
- throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
- }
- }
-
- @SuppressWarnings("unused")
private static void invokeNumberSetter(final Accessors gs, final MethodHandle invoker, final String name, final Object self, final double value) throws Throwable {
final Object func = gs.setter;
if (func instanceof ScriptFunction) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -52,9 +52,6 @@
/** Minimum chunk size for underlying arrays */
protected static final int CHUNK_SIZE = 32;
- /** Mask for getting a chunk */
- protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
-
/** Untouched data - still link callsites as IntArrayData, but expands to
* a proper ArrayData when we try to write to it */
public static final ArrayData EMPTY_ARRAY = new UntouchedArrayData();
@@ -164,11 +161,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- return toRealArrayData(index).set(index, value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
return toRealArrayData(index).set(index, value, strict);
}
@@ -179,11 +171,6 @@
}
@Override
- public long getLong(final int index) {
- throw new ArrayIndexOutOfBoundsException(index); //empty
- }
-
- @Override
public double getDouble(final int index) {
throw new ArrayIndexOutOfBoundsException(index); //empty
}
@@ -288,13 +275,13 @@
* @param length the initial length
* @return ArrayData
*/
- public static ArrayData allocate(final int length) {
- if (length == 0) {
+ public static ArrayData allocate(final long length) {
+ if (length == 0L) {
return new IntArrayData();
} else if (length >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(EMPTY_ARRAY, length);
} else {
- return new DeletedRangeArrayFilter(new IntArrayData(length), 0, length - 1);
+ return new DeletedRangeArrayFilter(new IntArrayData((int) length), 0, length - 1);
}
}
@@ -309,8 +296,6 @@
if (clazz == int[].class) {
return new IntArrayData((int[])array, ((int[])array).length);
- } else if (clazz == long[].class) {
- return new LongArrayData((long[])array, ((long[])array).length);
} else if (clazz == double[].class) {
return new NumberArrayData((double[])array, ((double[])array).length);
} else {
@@ -334,16 +319,6 @@
* @param array the array to use for initial elements
* @return the ArrayData
*/
- public static ArrayData allocate(final long[] array) {
- return new LongArrayData(array, array.length);
- }
-
- /**
- * Allocate an ArrayData wrapping a given array
- *
- * @param array the array to use for initial elements
- * @return the ArrayData
- */
public static ArrayData allocate(final double[] array) {
return new NumberArrayData(array, array.length);
}
@@ -537,16 +512,6 @@
public abstract ArrayData set(final int index, final int value, final boolean strict);
/**
- * Set a long value at a given index
- *
- * @param index the index
- * @param value the value
- * @param strict are we in strict mode
- * @return new array data (or same)
- */
- public abstract ArrayData set(final int index, final long value, final boolean strict);
-
- /**
* Set an double value at a given index
*
* @param index the index
@@ -609,26 +574,6 @@
}
/**
- * Get a long value from a given index
- *
- * @param index the index
- * @return the value
- */
- public abstract long getLong(final int index);
-
- /**
- * Get optimistic long - default is that it's impossible. Overridden
- * by arrays that actually represents longs or narrower
- *
- * @param index the index
- * @param programPoint program point
- * @return the value
- */
- public long getLongOptimistic(final int index, final int programPoint) {
- throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
- }
-
- /**
* Get a double value from a given index
*
* @param index the index
@@ -821,12 +766,8 @@
return Object.class;
}
final Class<?> itemClass = item.getClass();
- if (itemClass == Long.class) {
+ if (itemClass == Double.class || itemClass == Float.class || itemClass == Long.class) {
if (widest == Integer.class) {
- widest = Long.class;
- }
- } else if (itemClass == Double.class || itemClass == Float.class) {
- if (widest == Integer.class || widest == Long.class) {
widest = Double.class;
}
} else if (itemClass != Integer.class && itemClass != Short.class && itemClass != Byte.class) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -109,13 +109,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- underlying = underlying.set(index, value, strict);
- setLength(underlying.length());
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
underlying = underlying.set(index, value, strict);
setLength(underlying.length());
@@ -150,16 +143,6 @@
}
@Override
- public long getLong(final int index) {
- return underlying.getLong(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return underlying.getLongOptimistic(index, programPoint);
- }
-
- @Override
public double getDouble(final int index) {
return underlying.getDouble(index);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -122,12 +122,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- buf.put(index, (byte)value);
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
buf.put(index, (byte)value);
return this;
@@ -139,11 +133,6 @@
}
@Override
- public long getLong(final int index) {
- return 0x0ff & buf.get(index);
- }
-
- @Override
public double getDouble(final int index) {
return 0x0ff & buf.get(index);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -120,12 +120,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- deleted.clear(ArrayIndex.toLongIndex(index));
- return super.set(index, value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
deleted.clear(ArrayIndex.toLongIndex(index));
return super.set(index, value, strict);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -163,24 +163,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- final long longIndex = ArrayIndex.toLongIndex(index);
- if (longIndex < lo || longIndex > hi) {
- return super.set(index, value, strict);
- } else if (longIndex > lo && longIndex < hi) {
- return getDeletedArrayFilter().set(index, value, strict);
- }
- if (longIndex == lo) {
- lo++;
- } else {
- assert longIndex == hi;
- hi--;
- }
-
- return isEmpty() ? getUnderlying().set(index, value, strict) : super.set(index, value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
final long longIndex = ArrayIndex.toLongIndex(index);
if (longIndex < lo || longIndex > hi) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -57,14 +57,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (strict) {
- throw typeError("cant.set.property", Integer.toString(index), "frozen array");
- }
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (strict) {
throw typeError("cant.set.property", Integer.toString(index), "frozen array");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -156,22 +156,6 @@
return darray;
}
- private long[] toLongArray() {
- assert length() <= array.length : "length exceeds internal array size";
- final int len = (int)length();
- final long[] larray = new long[array.length];
-
- for (int index = 0; index < len; index++) {
- larray[index] = array[index];
- }
-
- return larray;
- }
-
- private LongArrayData convertToLong() {
- return new LongArrayData(toLongArray(), (int)length());
- }
-
private NumberArrayData convertToDouble() {
return new NumberArrayData(toDoubleArray(), (int)length());
}
@@ -184,8 +168,6 @@
public ArrayData convert(final Class<?> type) {
if (type == Integer.class || type == Byte.class || type == Short.class) {
return this;
- } else if (type == Long.class) {
- return convertToLong();
} else if (type == Double.class || type == Float.class) {
return convertToDouble();
} else {
@@ -253,17 +235,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (JSType.isRepresentableAsInt(value)) {
- array[index] = JSType.toInt32(value);
- setLength(Math.max(index + 1, length()));
- return this;
- }
-
- return convert(Long.class).set(index, value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (JSType.isRepresentableAsInt(value)) {
array[index] = (int)(long)value;
@@ -285,16 +256,6 @@
}
@Override
- public long getLong(final int index) {
- return array[index];
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return array[index];
- }
-
- @Override
public double getDouble(final int index) {
return array[index];
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Jan 06 14:54:24 2016 +0000
@@ -130,6 +130,6 @@
*
* @throws Throwable if invocation throws an exception/error
*/
- protected abstract boolean forEach(final Object val, final long i) throws Throwable;
+ protected abstract boolean forEach(final Object val, final double i) throws Throwable;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LengthNotWritableFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -91,22 +91,6 @@
}
@Override
- public long getLong(final int index) {
- if (index >= length()) {
- return JSType.toLong(get(index));
- }
- return underlying.getLong(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- if (index >= length()) {
- return JSType.toLongOptimistic(get(index), programPoint);
- }
- return underlying.getLongOptimistic(index, programPoint);
- }
-
- @Override
public double getDouble(final int index) {
if (index >= length()) {
return JSType.toNumber(get(index));
@@ -149,15 +133,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (checkAdd(index, value)) {
- return this;
- }
- underlying = underlying.set(index, value, strict);
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (checkAdd(index, value)) {
return this;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,406 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. 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.nashorn.internal.runtime.arrays;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.util.Arrays;
-import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
-
-/**
- * Implementation of {@link ArrayData} as soon as a long has been
- * written to the array
- */
-final class LongArrayData extends ContinuousArrayData implements IntOrLongElements {
- /**
- * The wrapped array
- */
- private long[] array;
-
- /**
- * Constructor
- * @param array an int array
- * @param length a length, not necessarily array.length
- */
- LongArrayData(final long array[], final int length) {
- super(length);
- assert array.length >= length;
- this.array = array;
- }
-
- @Override
- public final Class<?> getElementType() {
- return long.class;
- }
-
- @Override
- public final Class<?> getBoxedElementType() {
- return Long.class;
- }
-
- @Override
- public final ContinuousArrayData widest(final ContinuousArrayData otherData) {
- return otherData instanceof IntElements ? this : otherData;
- }
-
- @Override
- public final int getElementWeight() {
- return 2;
- }
-
- @Override
- public LongArrayData copy() {
- return new LongArrayData(array.clone(), (int)length());
- }
-
- @Override
- public Object[] asObjectArray() {
- return toObjectArray(true);
- }
-
- private Object[] toObjectArray(final boolean trim) {
- assert length() <= array.length : "length exceeds internal array size";
- final int len = (int)length();
- final Object[] oarray = new Object[trim ? len : array.length];
-
- for (int index = 0; index < len; index++) {
- oarray[index] = array[index];
- }
-
- return oarray;
- }
-
- @Override
- public Object asArrayOfType(final Class<?> componentType) {
- if (componentType == long.class) {
- final int len = (int)length();
- return array.length == len ? array.clone() : Arrays.copyOf(array, len);
- }
- return super.asArrayOfType(componentType);
- }
-
- private double[] toDoubleArray() {
- assert length() <= array.length : "length exceeds internal array size";
- final int len = (int)length();
- final double[] darray = new double[array.length];
-
- for (int index = 0; index < len; index++) {
- darray[index] = array[index];
- }
-
- return darray;
- }
-
- @Override
- public ContinuousArrayData convert(final Class<?> type) {
- if (type == Integer.class || type == Long.class || type == Byte.class || type == Short.class) {
- return this;
- }
- final int len = (int)length();
- if (type == Double.class || type == Float.class) {
- return new NumberArrayData(toDoubleArray(), len);
- }
- return new ObjectArrayData(toObjectArray(false), len);
- }
-
- @Override
- public void shiftLeft(final int by) {
- System.arraycopy(array, by, array, 0, array.length - by);
- }
-
- @Override
- public ArrayData shiftRight(final int by) {
- final ArrayData newData = ensure(by + length() - 1);
- if (newData != this) {
- newData.shiftRight(by);
- return newData;
- }
- System.arraycopy(array, 0, array, by, array.length - by);
-
- return this;
- }
-
- @Override
- public ArrayData ensure(final long safeIndex) {
- if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
- return new SparseArrayData(this, safeIndex + 1);
- }
- final int alen = array.length;
- if (safeIndex >= alen) {
- final int newLength = ArrayData.nextSize((int)safeIndex);
- array = Arrays.copyOf(array, newLength);
- }
- if (safeIndex >= length()) {
- setLength(safeIndex + 1);
- }
- return this;
- }
-
- @Override
- public ArrayData shrink(final long newLength) {
- Arrays.fill(array, (int)newLength, array.length, 0L);
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final Object value, final boolean strict) {
- if (value instanceof Long || value instanceof Integer ||
- value instanceof Byte || value instanceof Short) {
- return set(index, ((Number)value).longValue(), strict);
- } else if (value == ScriptRuntime.UNDEFINED) {
- return new UndefinedArrayFilter(this).set(index, value, strict);
- }
-
- final ArrayData newData = convert(value == null ? Object.class : value.getClass());
- return newData.set(index, value, strict);
- }
-
- @Override
- public ArrayData set(final int index, final int value, final boolean strict) {
- array[index] = value;
- setLength(Math.max(index + 1, length()));
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- array[index] = value;
- setLength(Math.max(index + 1, length()));
- return this;
- }
-
- @Override
- public ArrayData set(final int index, final double value, final boolean strict) {
- if (JSType.isRepresentableAsLong(value)) {
- array[index] = (long)value;
- setLength(Math.max(index + 1, length()));
- return this;
- }
- return convert(Double.class).set(index, value, strict);
- }
-
- private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
- private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
-
- @SuppressWarnings("unused")
- private long getElem(final int index) {
- if (has(index)) {
- return array[index];
- }
- throw new ClassCastException();
- }
-
- @SuppressWarnings("unused")
- private void setElem(final int index, final long elem) {
- if (hasRoomFor(index)) {
- array[index] = elem;
- return;
- }
- throw new ClassCastException();
- }
-
- @Override
- public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
- if (returnType == int.class) {
- return null;
- }
- return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
- }
-
- @Override
- public MethodHandle getElementSetter(final Class<?> elementType) {
- return elementType == int.class || elementType == long.class ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
- }
-
- @Override
- public int getInt(final int index) {
- return JSType.toInt32(array[index]);
- }
-
- @Override
- public long getLong(final int index) {
- return array[index];
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- return array[index];
- }
-
- @Override
- public double getDouble(final int index) {
- return array[index];
- }
-
- @Override
- public double getDoubleOptimistic(final int index, final int programPoint) {
- return array[index];
- }
-
- @Override
- public Object getObject(final int index) {
- return array[index];
- }
-
- @Override
- public boolean has(final int index) {
- return 0 <= index && index < length();
- }
-
- @Override
- public ArrayData delete(final int index) {
- return new DeletedRangeArrayFilter(this, index, index);
- }
-
- @Override
- public ArrayData delete(final long fromIndex, final long toIndex) {
- return new DeletedRangeArrayFilter(this, fromIndex, toIndex);
- }
-
- @Override
- public Object pop() {
- final int len = (int)length();
- if (len == 0) {
- return ScriptRuntime.UNDEFINED;
- }
-
- final int newLength = len - 1;
- final long elem = array[newLength];
- array[newLength] = 0;
- setLength(newLength);
-
- return elem;
- }
-
- @Override
- public ArrayData slice(final long from, final long to) {
- final long start = from < 0 ? from + length() : from;
- final long newLength = to - start;
- return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
- }
-
- @Override
- public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
- final long oldLength = length();
- final long newLength = oldLength - removed + added;
- if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
- throw new UnsupportedOperationException();
- }
- final ArrayData returnValue = removed == 0 ?
- EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
-
- if (newLength != oldLength) {
- final long[] newArray;
-
- if (newLength > array.length) {
- newArray = new long[ArrayData.nextSize((int)newLength)];
- System.arraycopy(array, 0, newArray, 0, start);
- } else {
- newArray = array;
- }
-
- System.arraycopy(array, start + removed, newArray, start + added, (int)(oldLength - start - removed));
- array = newArray;
- setLength(newLength);
- }
-
- return returnValue;
- }
-
- @Override
- public long fastPush(final int arg) {
- return fastPush((long)arg);
- }
-
- @Override
- public long fastPush(final long arg) {
- final int len = (int)length();
- if (len == array.length) {
- array = Arrays.copyOf(array, nextSize(len));
- }
- array[len] = arg;
- return increaseLength();
- }
-
- @Override
- public long fastPopLong() {
- if (length() == 0) {
- throw new ClassCastException(); //undefined result
- }
- final int newLength = (int)decreaseLength();
- final long elem = array[newLength];
- array[newLength] = 0;
- return elem;
- }
-
- @Override
- public double fastPopDouble() {
- return fastPopLong();
- }
-
- @Override
- public Object fastPopObject() {
- return fastPopLong();
- }
-
- @Override
- public ContinuousArrayData fastConcat(final ContinuousArrayData otherData) {
- final int otherLength = (int)otherData.length();
- final int thisLength = (int)length();
- assert otherLength > 0 && thisLength > 0;
-
- final long[] otherArray = ((LongArrayData)otherData).array;
- final int newLength = otherLength + thisLength;
- final long[] newArray = new long[ArrayData.alignUp(newLength)];
-
- System.arraycopy(array, 0, newArray, 0, thisLength);
- System.arraycopy(otherArray, 0, newArray, thisLength, otherLength);
-
- return new LongArrayData(newArray, newLength);
- }
-
- @Override
- public String toString() {
- assert length() <= array.length : length() + " > " + array.length;
-
- final StringBuilder sb = new StringBuilder(getClass().getSimpleName()).
- append(": [");
- final int len = (int)length();
- for (int i = 0; i < len; i++) {
- sb.append(array[i]).append('L'); //make sure L suffix is on elements, to discriminate this from IntArrayData.toString()
- if (i + 1 < len) {
- sb.append(", ");
- }
- }
- sb.append(']');
-
- return sb.toString();
- }
-}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NonExtensibleArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -51,14 +51,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (has(index)) {
- return underlying.set(index, value, strict);
- }
- return extensionCheck(strict, index);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (has(index)) {
return underlying.set(index, value, strict);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -179,13 +179,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- array[index] = value;
- setLength(Math.max(index + 1, length()));
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
array[index] = value;
setLength(Math.max(index + 1, length()));
@@ -214,7 +207,7 @@
@Override
public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
- if (returnType == int.class || returnType == long.class) {
+ if (returnType == int.class) {
return null;
}
return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
@@ -231,11 +224,6 @@
}
@Override
- public long getLong(final int index) {
- return (long)array[index];
- }
-
- @Override
public double getDouble(final int index) {
return array[index];
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -150,13 +150,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- array[index] = value;
- setLength(Math.max(index + 1, length()));
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
array[index] = value;
setLength(Math.max(index + 1, length()));
@@ -216,11 +209,6 @@
}
@Override
- public long getLong(final int index) {
- return JSType.toLong(array[index]);
- }
-
- @Override
public double getDouble(final int index) {
return JSType.toNumber(array[index]);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Wed Jan 06 14:54:24 2016 +0000
@@ -195,21 +195,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- if (index >= 0 && index < maxDenseLength) {
- final long oldLength = underlying.length();
- ensure(index);
- underlying = underlying.set(index, value, strict).safeDelete(oldLength, index - 1, strict);
- setLength(Math.max(underlying.length(), length()));
- } else {
- final Long longIndex = indexToKey(index);
- sparseMap.put(longIndex, value);
- setLength(Math.max(longIndex + 1, length()));
- }
- return this;
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
if (index >= 0 && index < maxDenseLength) {
final long oldLength = underlying.length();
@@ -258,22 +243,6 @@
}
@Override
- public long getLong(final int index) {
- if (index >= 0 && index < maxDenseLength) {
- return underlying.getLong(index);
- }
- return JSType.toLong(sparseMap.get(indexToKey(index)));
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- if (index >= 0 && index < maxDenseLength) {
- return underlying.getLongOptimistic(index, programPoint);
- }
- return JSType.toLongOptimistic(sparseMap.get(indexToKey(index)), programPoint);
- }
-
- @Override
public double getDouble(final int index) {
if (index >= 0 && index < maxDenseLength) {
return underlying.getDouble(index);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java Wed Jan 06 14:54:24 2016 +0000
@@ -128,13 +128,6 @@
}
@Override
- public ArrayData set(final int index, final long value, final boolean strict) {
- undefined.clear(index);
-
- return super.set(index, value, strict);
- }
-
- @Override
public ArrayData set(final int index, final double value, final boolean strict) {
undefined.clear(index);
@@ -160,24 +153,6 @@
}
@Override
- public long getLong(final int index) {
- if (undefined.isSet(index)) {
- return 0L;
- }
-
- return super.getLong(index);
- }
-
- @Override
- public long getLongOptimistic(final int index, final int programPoint) {
- if (undefined.isSet(index)) {
- throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
- }
-
- return super.getLongOptimistic(index, programPoint);
- }
-
- @Override
public double getDouble(final int index) {
if (undefined.isSet(index)) {
return Double.NaN;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jan 06 14:54:24 2016 +0000
@@ -201,7 +201,7 @@
*
* @return callsite for a math intrinsic node
*/
- public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
+ public static CallSite mathBootstrap(final Lookup lookup, final String name, final MethodType type, final int programPoint) {
final MethodHandle mh;
switch (name) {
case "iadd":
@@ -222,24 +222,6 @@
case "ineg":
mh = JSType.NEGATE_EXACT.methodHandle();
break;
- case "ladd":
- mh = JSType.ADD_EXACT_LONG.methodHandle();
- break;
- case "lsub":
- mh = JSType.SUB_EXACT_LONG.methodHandle();
- break;
- case "lmul":
- mh = JSType.MUL_EXACT_LONG.methodHandle();
- break;
- case "ldiv":
- mh = JSType.DIV_EXACT_LONG.methodHandle();
- break;
- case "lrem":
- mh = JSType.REM_EXACT_LONG.methodHandle();
- break;
- case "lneg":
- mh = JSType.NEGATE_EXACT_LONG.methodHandle();
- break;
default:
throw new AssertionError("unsupported math intrinsic");
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Jan 06 14:54:24 2016 +0000
@@ -48,19 +48,8 @@
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects.
*/
final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
- private static ClassLoader extLoader;
- static {
- extLoader = BrowserJSObjectLinker.class.getClassLoader();
- // in case nashorn is loaded as bootstrap!
- if (extLoader == null) {
- extLoader = ClassLoader.getSystemClassLoader().getParent();
- }
- }
-
private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject";
- // not final because this is lazily initialized
- // when we hit a subclass for the first time.
- private static volatile Class<?> jsObjectClass;
+ private static final Class<?> jsObjectClass = findBrowserJSObjectClass();
private final NashornBeansLinker nashornBeansLinker;
BrowserJSObjectLinker(final NashornBeansLinker nashornBeansLinker) {
@@ -73,22 +62,7 @@
}
static boolean canLinkTypeStatic(final Class<?> type) {
- if (jsObjectClass != null && jsObjectClass.isAssignableFrom(type)) {
- return true;
- }
-
- // check if this class is a subclass of JSObject
- Class<?> clazz = type;
- while (clazz != null) {
- if (clazz.getClassLoader() == extLoader &&
- clazz.getName().equals(JSOBJECT_CLASS)) {
- jsObjectClass = clazz;
- return true;
- }
- clazz = clazz.getSuperclass();
- }
-
- return false;
+ return jsObjectClass != null && jsObjectClass.isAssignableFrom(type);
}
private static void checkJSObjectClass() {
@@ -101,13 +75,10 @@
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
checkJSObjectClass();
- GuardedInvocation inv;
- if (jsObjectClass.isInstance(self)) {
- inv = lookup(desc, request, linkerServices);
- inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
- } else {
- throw new AssertionError(); // Should never reach here.
- }
+ assert jsObjectClass.isInstance(self);
+
+ GuardedInvocation inv = lookup(desc, request, linkerServices);
+ inv = inv.replaceMethods(linkerServices.filterInternalObjects(inv.getInvocation()), inv.getGuard());
return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
}
@@ -122,7 +93,7 @@
final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
if (op == null) {
- return null;
+ return inv;
}
final String name = NashornCallSiteDescriptor.getOperand(desc);
switch (op) {
@@ -236,4 +207,18 @@
return MH.findVirtual(MethodHandles.publicLookup(), jsObjectClass, name, MH.type(rtype, types));
}
}
+
+ private static Class<?> findBrowserJSObjectClass() {
+ ClassLoader extLoader;
+ extLoader = BrowserJSObjectLinker.class.getClassLoader();
+ // in case nashorn is loaded as bootstrap!
+ if (extLoader == null) {
+ extLoader = ClassLoader.getSystemClassLoader().getParent();
+ }
+ try {
+ return Class.forName(JSOBJECT_CLASS, false, extLoader);
+ } catch (final ClassNotFoundException e) {
+ return null;
+ }
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Wed Jan 06 14:54:24 2016 +0000
@@ -141,8 +141,9 @@
}
/**
- * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType(Class, Class)} that doesn't
- * care about adapting the method signature; that's done by the invoking method. Returns conversion from Object to String/number/boolean (JS primitive types).
+ * Main part of the implementation of {@link GuardingTypeConverterFactory#convertToType} that doesn't
+ * care about adapting the method signature; that's done by the invoking method. Returns conversion
+ * from Object to String/number/boolean (JS primitive types).
* @param sourceType the source type
* @param targetType the target type
* @return a guarded invocation that converts from the source type to the target type.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jan 06 14:54:24 2016 +0000
@@ -174,28 +174,31 @@
* Function used by {@link NashornTextifier} to represent call site flags in
* human readable form
* @param flags call site flags
- * @return human readable form of this callsite descriptor
+ * @param sb the string builder
*/
- public static String toString(final int flags) {
- final StringBuilder sb = new StringBuilder();
+ public static void appendFlags(final int flags, final StringBuilder sb) {
+ final int pp = flags >> CALLSITE_PROGRAM_POINT_SHIFT;
+ if (pp != 0) {
+ sb.append(" pp=").append(pp);
+ }
if ((flags & CALLSITE_SCOPE) != 0) {
if ((flags & CALLSITE_FAST_SCOPE) != 0) {
- sb.append("fastscope ");
+ sb.append(" fastscope");
} else {
- assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
- sb.append("scope ");
+ sb.append(" scope");
}
if ((flags & CALLSITE_DECLARE) != 0) {
- sb.append("declare ");
+ sb.append(" declare");
}
+ } else {
+ assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
}
if ((flags & CALLSITE_APPLY_TO_CALL) != 0) {
- sb.append("apply2call ");
+ sb.append(" apply2call");
}
if ((flags & CALLSITE_STRICT) != 0) {
- sb.append("strict ");
+ sb.append(" strict");
}
- return sb.length() == 0 ? "" : " " + sb.toString().trim();
}
/**
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Functions.properties Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,44 @@
+Object.setIndexedPropertiesToExternalArrayData=sets ByteBuffer to hold indexed data (nashorn extension)
+
+Object.getPrototypeOf=returns the prototype of the specified object
+
+Object.setPrototypeOf=sets the prototype of the given object (ES6)
+
+Object.getOwnPropertyDescriptor=returns a property descriptor for an own property (not inherited property)
+
+Object.getOwnPropertyNames=returns an array of all properties (enumerable or not) found directly on the given object
+
+Object.getOwnPropertySymbols=returns an array of all symbol properties found directly on the given object (ES6)
+
+Object.create=creates a new object with the specified prototype object and properties
+
+Object.defineProperty=adds an own property and/or update the attributes of an existing own property of an object
+
+Object.defineProperties=defines new or modifies existing properties directly on the given object
+
+Object.seal=prevents new properties from being added to the given object and marks existing properties as non-configurable
+
+Object.freeze=prevents new properties from being added to the given object and prevents existing properties from being removed or re-configured
+
+Object.preventExtensions=prevents new properties from ever being added to the given object
+
+Object.isSealed=tells if an object is sealed or not
+
+Object.isFrozen=tells if an object is fronzen or not
+
+Object.isExtensible=tells if an object is extensible or not
+
+Object.keys=returns an array of the given object's own enumerable properties
+
+Object=creates a new script object or converts given value as a script object
+
+Object.prototype.toString=returns a string representing of this object
+
+Object.prototype.hasOwnProperty=tells whether this object has the specified property or not
+
+Object.prototype.isPrototypeOf=tests for this object in another object's prototype chain
+
+Object.prototype.propertyIsEnumerable=tells whether the given property is enumerable or not
+
+Object.bindProperties=binds the source object's properties to the target object (nashorn extension)
+
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Jan 06 14:54:24 2016 +0000
@@ -25,23 +25,6 @@
package jdk.nashorn.tools;
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.*;
-import java.util.stream.Collectors;
-
import jdk.nashorn.api.scripting.NashornException;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
@@ -60,10 +43,32 @@
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Symbol;
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
import jdk.nashorn.internal.runtime.options.Options;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
/**
* Command line Shell for processing JavaScript files.
*/
@@ -203,8 +208,7 @@
// parse options
if (args != null) {
try {
- // FIXME: preprocessArgs does not yet work fine
- final String[] prepArgs = args; // preprocessArgs(args);
+ final String[] prepArgs = preprocessArgs(args);
options.process(prepArgs);
} catch (final IllegalArgumentException e) {
werr.println(bundle.getString("shell.usage"));
@@ -236,35 +240,53 @@
}
/**
- * Preprocess the command line arguments passed in by the shell. This checks, for each of the arguments, whether it
- * can be a file name, and if so, whether the file exists. If the file exists and begins with a shebang line, and
- * the arguments on that line are a prefix of {@code args} with the file removed, it is assumed that a script file
- * being executed via shebang was found, and it is moved to the appropriate position in the argument list. The first
- * such match is used.
+ * Preprocess the command line arguments passed in by the shell. This method checks, for the first non-option
+ * argument, whether the file denoted by it begins with a shebang line. If so, it is assumed that execution in
+ * shebang mode is intended. The consequence of this is that the identified script file will be treated as the
+ * <em>only</em> script file, and all subsequent arguments will be regarded as arguments to the script.
* <p>
- * This method canonicalizes the command line arguments to the form {@code <options> <scripts> -- <arguments>},
- * where the last of the {@code scripts} is the one being run in shebang fashion.
+ * This method canonicalizes the command line arguments to the form {@code <options> <script> -- <arguments>} if a
+ * shebang script is identified. On platforms that pass shebang arguments as single strings, the shebang arguments
+ * will be broken down into single arguments; whitespace is used as separator.
+ * <p>
+ * Shebang mode is entered regardless of whether the script is actually run directly from the shell, or indirectly
+ * via the {@code jjs} executable. It is the user's / script author's responsibility to ensure that the arguments
+ * given on the shebang line do not lead to a malformed argument sequence. In particular, the shebang arguments
+ * should not contain any whitespace for purposes other than separating arguments, as the different platforms deal
+ * with whitespace in different and incompatible ways.
* <p>
* @implNote Example:<ul>
- * <li>Shebang line in {@code script.js}: {@code #!/path/to/jjs --language=es6 other.js -- arg1}</li>
+ * <li>Shebang line in {@code script.js}: {@code #!/path/to/jjs --language=es6}</li>
* <li>Command line: {@code ./script.js arg2}</li>
- * <li>{@code args} array passed to Nashorn: {@code --language=es6,other.js,--,arg1,./script.js,arg2}</li>
- * <li>Required canonicalized arguments array: {@code --language=es6,other.js,./script.js,--,arg1,arg2}</li>
+ * <li>{@code args} array passed to Nashorn: {@code --language=es6,./script.js,arg}</li>
+ * <li>Required canonicalized arguments array: {@code --language=es6,./script.js,--,arg2}</li>
* </ul>
*
* @param args the command line arguments as passed into Nashorn.
- * @return a properly ordered argument list
+ * @return the passed and possibly canonicalized argument list
*/
private static String[] preprocessArgs(final String[] args) {
- final List<String> largs = new ArrayList<>();
- Collections.addAll(largs, args);
- final List<String> pa = new ArrayList<>();
- String scriptFile = null;
- boolean found = false;
- for (int i = 0; i < args.length; ++i) {
- final String a = args[i];
- final Path p = Paths.get(a);
- if (!found && (!a.startsWith("-") || a.length() == 1) && Files.exists(p)) {
+ if (args.length == 0) {
+ return args;
+ }
+
+ final List<String> processedArgs = new ArrayList<>();
+ processedArgs.addAll(Arrays.asList(args));
+
+ // Nashorn supports passing multiple shebang arguments. On platforms that pass anything following the
+ // shebang interpreter notice as one argument, the first element of the argument array needs to be special-cased
+ // as it might actually contain several arguments. Mac OS X splits shebang arguments, other platforms don't.
+ // This special handling is also only necessary if the first argument actually starts with an option.
+ if (args[0].startsWith("-") && !System.getProperty("os.name", "generic").startsWith("Mac OS X")) {
+ processedArgs.addAll(0, ScriptingFunctions.tokenizeString(processedArgs.remove(0)));
+ }
+
+ int shebangFilePos = -1; // -1 signifies "none found"
+ // identify a shebang file and its position in the arguments array (if any)
+ for (int i = 0; i < processedArgs.size(); ++i) {
+ final String a = processedArgs.get(i);
+ if (!a.startsWith("-")) {
+ final Path p = Paths.get(a);
String l = "";
try (final BufferedReader r = Files.newBufferedReader(p)) {
l = r.readLine();
@@ -272,35 +294,18 @@
// ignore
}
if (l.startsWith("#!")) {
- List<String> shebangArgs = Arrays.asList(l.split(" "));
- shebangArgs = shebangArgs.subList(1, shebangArgs.size()); // remove #! part
- final int ssize = shebangArgs.size();
- final List<String> filteredArgs = largs.stream().filter(x -> !x.equals(a)).collect(Collectors.toList());
- if (filteredArgs.size() >= ssize && shebangArgs.equals(filteredArgs.subList(0, ssize))) {
- scriptFile = a;
- found = true;
- continue;
- }
+ shebangFilePos = i;
}
+ // We're only checking the first non-option argument. If it's not a shebang file, we're in normal
+ // execution mode.
+ break;
}
- pa.add(a);
}
- if (scriptFile != null) {
- // Insert the found script file name either before a -- argument, or at the end of the options list, before
- // any other arguments, with an extra --.
- int argidx = pa.indexOf("--");
- if (argidx == -1) {
- for (String s : pa) {
- ++argidx;
- if (s.charAt(0) != '-') {
- pa.add(argidx, "--");
- break;
- }
- }
- }
- pa.add(argidx, scriptFile);
+ if (shebangFilePos != -1) {
+ // Insert the argument separator after the shebang script file.
+ processedArgs.add(shebangFilePos + 1, "--");
}
- return pa.stream().toArray(String[]::new);
+ return processedArgs.stream().toArray(String[]::new);
}
/**
--- a/nashorn/test/script/basic/JDK-8062799.js Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/script/basic/JDK-8062799.js Wed Jan 06 14:54:24 2016 +0000
@@ -33,67 +33,46 @@
var b = true;
var i = 1;
- var l = 4294967296;
var d = 2.1;
var o = "foo";
print(inspect(b || b, "b || b"));
print(inspect(b || i, "b || i"));
- print(inspect(b || l, "b || l"));
print(inspect(b || d, "b || d"));
print(inspect(b || o, "b || o"));
print(inspect(i || b, "i || b"));
print(inspect(i || i, "i || i"));
- print(inspect(i || l, "i || l"));
print(inspect(i || d, "i || d"));
print(inspect(i || o, "i || o"));
- print(inspect(l || b, "l || b"));
- print(inspect(l || i, "l || i"));
- print(inspect(l || l, "l || l"));
- print(inspect(l || d, "l || d"));
- print(inspect(l || o, "l || o"));
-
print(inspect(d || b, "d || b"));
print(inspect(d || i, "d || i"));
- print(inspect(d || l, "d || l"));
print(inspect(d || d, "d || d"));
print(inspect(d || o, "d || o"));
print(inspect(o || b, "o || b"));
print(inspect(o || i, "o || i"));
- print(inspect(o || l, "o || l"));
print(inspect(o || d, "o || d"));
print(inspect(o || o, "o || o"));
print(inspect(b && b, "b && b"));
print(inspect(b && i, "b && i"));
- print(inspect(b && l, "b && l"));
print(inspect(b && d, "b && d"));
print(inspect(b && o, "b && o"));
print(inspect(i && b, "i && b"));
print(inspect(i && i, "i && i"));
- print(inspect(i && l, "i && l"));
print(inspect(i && d, "i && d"));
print(inspect(i && o, "i && o"));
- print(inspect(l && b, "l && b"));
- print(inspect(l && i, "l && i"));
- print(inspect(l && l, "l && l"));
- print(inspect(l && d, "l && d"));
- print(inspect(l && o, "l && o"));
-
print(inspect(d && b, "d && b"));
print(inspect(d && i, "d && i"));
- print(inspect(d && l, "d && l"));
print(inspect(d && d, "d && d"));
print(inspect(d && o, "d && o"));
print(inspect(o && b, "o && b"));
print(inspect(o && i, "o && i"));
- print(inspect(o && l, "o && l"));
print(inspect(o && d, "o && d"));
print(inspect(o && o, "o && o"));
})();
--- a/nashorn/test/script/basic/JDK-8062799.js.EXPECTED Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/script/basic/JDK-8062799.js.EXPECTED Wed Jan 06 14:54:24 2016 +0000
@@ -1,50 +1,32 @@
b || b: boolean
b || i: boolean
-b || l: boolean
b || d: boolean
b || o: boolean
i || b: int
i || i: int
-i || l: long
i || d: double
i || o: int
-l || b: long
-l || i: long
-l || l: long
-l || d: double
-l || o: long
d || b: double
d || i: double
-d || l: double
d || d: double
d || o: double
o || b: object
o || i: object
-o || l: object
o || d: object
o || o: object
b && b: boolean
b && i: int
-b && l: long
b && d: double
b && o: object
i && b: boolean
i && i: int
-i && l: long
i && d: double
i && o: object
-l && b: boolean
-l && i: long
-l && l: long
-l && d: double
-l && o: object
d && b: boolean
d && i: double
-d && l: double
d && d: double
d && o: object
o && b: boolean
o && i: int
-o && l: long
o && d: double
o && o: object
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8144020.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8144020: Remove long as an internal numeric type
+ *
+ * @test
+ * @run
+ */
+
+var LongProvider = Java.type("jdk.nashorn.test.models.LongProvider");
+var Long = Java.type("java.lang.Long");
+var LongClass = Long.class;
+var Integer = Java.type("java.lang.Integer");
+var Double = Java.type("java.lang.Double");
+
+var INT = "3";
+var DOUBLE = "5.5";
+var MAX_LONG = "9223372036854775807";
+var MIN_LONG = "-9223372036854775808";
+var BIG_LONG = "281474976710655"; // can be represented as double
+var NEG_LONG = "-281474976710656"; // can be represented as double
+var SMALL_LONG = "13";
+
+// Make sure we can pass longs from and to Java without losing precision
+LongProvider.checkLong(LongProvider.getLong(MAX_LONG), MAX_LONG);
+LongProvider.checkLong(LongProvider.getLong(MIN_LONG), MIN_LONG);
+LongProvider.checkLong(LongProvider.getLong(BIG_LONG), BIG_LONG);
+LongProvider.checkLong(LongProvider.getLong(NEG_LONG), NEG_LONG);
+LongProvider.checkLong(LongProvider.getLong(SMALL_LONG), SMALL_LONG);
+
+// a polymorphic function that can return various number types
+function getNumber(str) {
+ switch (str) {
+ case INT: return +INT;
+ case DOUBLE: return +DOUBLE;
+ default: return Long.parseLong(str);
+ }
+}
+
+function compareValue(n, str) {
+ switch (str) {
+ case INT: return Integer.compare(n, Integer.parseInt(str) == 0);
+ case DOUBLE: return Double.compare(n, Double.parseDouble(str) == 0);
+ default: return Long.compare(n, Long.parseLong(str) == 0);
+ }
+}
+
+// Call a a function with a sequence of values. The purpose of this is that we can handle
+// longs without losing precision in the presence of optimistic deoptimization, cached callsites, etc.
+function testSequence(fn, values) {
+ for (var i in values) {
+ fn(values[i]);
+ }
+}
+
+// We need to use "fresh" (unlinked and un-deoptimized) functions for each of the test runs.
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [INT, BIG_LONG, MIN_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [INT, MAX_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [INT, DOUBLE, NEG_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [DOUBLE, MAX_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [DOUBLE, SMALL_LONG, MAX_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [INT, DOUBLE, NEG_LONG, MAX_LONG]);
+
+testSequence(function(str) {
+ var n = getNumber(str);
+ Assert.assertTrue(compareValue(n, str));
+}, [DOUBLE, MAX_LONG, DOUBLE, INT]);
+
+// Make sure long arrays make it through Java.from and Java.to without losing precision
+var longArrayType = Java.type("long[]");
+for (var i = 0; i < 3; i++) {
+ LongProvider.checkLongArray(Java.to(Java.from(LongProvider.getLongArray(i)), longArrayType), i);
+}
+
+l = Long.parseLong(BIG_LONG);
+Assert.assertTrue(l >>> 8 === 0xffffff);
+Assert.assertTrue(l << 8 === -0x100);
+Assert.assertTrue(l + 1 === 0x1000000000000);
+Assert.assertTrue(l - 1 === 0xfffffffffffe);
+
+Assert.assertEquals(LongProvider.getLong(MAX_LONG).getClass(), LongClass);
+Assert.assertEquals(LongProvider.getLong(MIN_LONG).getClass(), LongClass);
--- a/nashorn/test/script/basic/JDK-8144131.js Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/script/basic/JDK-8144131.js Wed Jan 06 14:54:24 2016 +0000
@@ -30,12 +30,9 @@
var doubleArray = [97912312397.234, -182374983434.56];
var doubleArrayResults = [-871935411, -1986357002];
-var longArray = [0x7fffffff8c102ebc, -0x7fffffffe9dfec18];
-var longArrayResults = [-1945096192, 371201024];
-// Make sure arrays use double and long array data
+// Make sure array uses double array data
Assert.assertEquals(doubleArray[0].getClass(), java.lang.Double.class);
-Assert.assertEquals(longArray[0].getClass(), java.lang.Long.class);
function testBinaryOp(array, index, expected) {
Assert.assertEquals(array[index] & 0xffffffff, expected);
@@ -44,7 +41,4 @@
for (var i = 0; i < doubleArray.length; i++) {
testBinaryOp(doubleArray, i, doubleArrayResults[i]);
}
-for (var i = 0; i < longArray.length; i++) {
- testBinaryOp(longArray, i, longArrayResults[i]);
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8145550.js Wed Jan 06 14:54:24 2016 +0000
@@ -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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8141537: Megamorphic invoke should use CompiledFunction variants without any LinkLogic
+ *
+ * @test
+ * @option --unstable-relink-threshold=1
+ * @run
+ */
+
+load(__DIR__ + "NASHORN-421.js")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8146147.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8146147: Java linker indexed property getter does not work for computed nashorn string
+ *
+ * @test
+ * @run
+ */
+
+var locale = java.util.Locale.ENGLISH;
+var prop = 'ISO3Language';
+var prop1 = 'ISO3';
+var prop2 = prop1 + 'Language';
+var prop3 = String(prop2);
+
+function checkLang(obj) {
+ if (obj != "eng") {
+ throw new Error("FAILED: expected 'eng', got " + obj);
+ }
+}
+
+checkLang(locale.ISO3Language);
+checkLang(locale['ISO3Language']);
+checkLang(locale[prop]);
+checkLang(locale[prop1 + 'Language']);
+checkLang(locale[prop2]);
+checkLang(locale[prop3]);
+checkLang(locale[String(prop1 + 'Language')]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/apply_to_call/JDK-8145669.js Wed Jan 06 14:54:24 2016 +0000
@@ -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.
+ *
+ * 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.
+ */
+
+/*
+ * JDK-8145669: apply2call optimized callsite fails after becoming megamorphic
+ *
+ * @test
+ * @option --unstable-relink-threshold=1
+ * @run
+ */
+
+load(__DIR__ + "apply_to_call2.js");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/apply_to_call/JDK-8145669.js.EXPECTED Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting call now
+1
+2
+3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/apply_to_call/JDK-8145669_2.js Wed Jan 06 14:54:24 2016 +0000
@@ -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.
+ *
+ * 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.
+ */
+
+/**
+ * JDK-8145669: apply2call optimized callsite fails after becoming megamorphic
+ *
+ * @test
+ * @option --unstable-relink-threshold=1
+ * @run
+ */
+
+load(__DIR__ + "apply_to_call_varargs.js");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/apply_to_call/JDK-8145669_2.js.EXPECTED Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,66 @@
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+Swapping out call
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+All done!
--- a/nashorn/test/script/nosecurity/JDK-8067215.js Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/script/nosecurity/JDK-8067215.js Wed Jan 06 14:54:24 2016 +0000
@@ -32,7 +32,6 @@
var intType = Java.type("int");
var doubleType = Java.type("double");
-var longType = Java.type("long");
var objectType = Java.type("java.lang.Object");
var Context = Java.type("jdk.nashorn.internal.runtime.Context");
@@ -58,7 +57,6 @@
}
if (prop.getType() != getExpectedType(obj[key])) {
throw new Error("Wrong property type: " + prop.getType() + " // " + getExpectedType(obj[key]));
-
}
}
}
@@ -67,14 +65,8 @@
if (!dualFields) {
return objectType.class;
}
- if (JSType.isRepresentableAsInt(value)) {
- return intType.class;
- }
- if (JSType.isRepresentableAsLong(value)) {
- return longType.class;
- }
- if (JSType.isNumber(value)) {
- return doubleType.class;
+ if (typeof value === "number") {
+ return JSType.isRepresentableAsInt(value) ? intType.class : doubleType.class;
}
return objectType.class;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/JDK-8144221.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,155 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test that shebang handling works properly.
+ *
+ * @test
+ * @runif os.not.windows
+ * @option -scripting
+ * @run
+ */
+
+// The test generates three different JavaScript source files. The first two
+// are generated at the beginning of the test and do not change.
+// * a.js
+// print("A: " + arguments)
+// * b.js
+// #!<path_to_jjs> -lalelu -- ignore
+// print("B: " + arguments)
+//
+// The third file, shebang.js, is generated differently for each particular
+// test case, containing different shebang lines and one statement:
+// * shebang.js
+// #!<path_to_jjs> <shebang_line>
+// print("S: " + arguments)
+//
+// The path_to_jjs is extracted from the environment based on JAVA_HOME, so the
+// latter must be set properly.
+//
+// Each shebang.js is run four times, in all possible combinations of values
+// from the following two axes:
+// * without passing any arguments, and passing the arguments 'a.js' and
+// '"hello world"' (the latter being a quoted string);
+// * run via jjs, and via direct shell execution (using shebang).
+
+var pseudosheb = "#!${jjs} -lalelu -- ignore",
+ System = Java.type('java.lang.System'),
+ Paths = Java.type('java.nio.file.Paths'),
+ Files = Java.type('java.nio.file.Files'),
+ Opt = Java.type('java.nio.file.StandardOpenOption'),
+ Arrays = Java.type('java.util.Arrays')
+
+var sep = Java.type('java.io.File').separator,
+ win = System.getProperty("os.name").startsWith("Windows"),
+ jjsName = "jjs" + (win ? ".exe" : ""),
+ javaHome = System.getProperty("java.home")
+
+var jjs = javaHome + "/../bin/".replace(/\//g, sep) + jjsName
+if (!Files.exists(Paths.get(jjs))) {
+ jjs = javaHome + "/bin/".replace(/\//g, sep) + jjsName
+}
+
+// Create and cwd to a temporary directory.
+
+var tmpdir = Files.createTempDirectory(null),
+ tmp = tmpdir.toAbsolutePath().toString(),
+ curpwd = $ENV.PWD
+
+$ENV.PWD = tmp
+
+// Test cases. Each case is documented with the expected output for the four
+// different executions.
+
+var shebs = [
+ // No arguments on the shebang line.
+ // noargs jjs/shebang -> no output but "S" prefix
+ // args jjs/shebang -> output the arguments with "S" prefix
+ "",
+ // One interpreter argument.
+ // noargs jjs/shebang -> no output but "S" prefix
+ // args jjs/shebang -> output the arguments with "S" prefix
+ "--language=es6",
+ // Two interpreter arguments.
+ // noargs jjs/shebang -> no output but "S" prefix
+ // args jjs/shebang -> output the arguments with "S" prefix
+ "--language=es6 -scripting",
+ // One interpreter argument and a JavaScript file without shebang.
+ // (For shebang execution, this is a pathological example, as the
+ // JavaScript file passed as a shebang argument will be analyzed and
+ // shebang mode will not be entered.)
+ // noargs jjs -> no output but "S" prefix
+ // args jjs -> output the arguments with "S" prefix
+ // noargs shebang -> no output but "A" and "S" prefixes
+ // args shebang -> output "A", "S", and "A" prefixes, then the error
+ // message:
+ // "java.io.IOException: hello world is not a file"
+ "-scripting a.js",
+ // One interpreter argument and a JavaScript file with shebang. (This
+ // is another pathological example, as it will force shebang mode,
+ // leading to all subsequent arguments, including shebang.js, being
+ // treated as arguments to the script b.js.)
+ // noargs jjs -> no output but the "S" prefix
+ // args jjs -> output the arguments with "S" prefix
+ // noargs shebang -> output shebang.js with "B" prefix
+ // args shebang -> output shebang.js and the arguments with "B"
+ // prefix
+ "-scripting b.js"
+ ]
+
+function write(file, lines) {
+ Files.write(Paths.get(tmp, file), Arrays.asList(lines), Opt.CREATE, Opt.WRITE)
+}
+
+function insn(name) {
+ return "print('${name}:' + arguments)"
+}
+
+function run(viajjs, name, arg1, arg2) {
+ var prefix = viajjs ? "${jjs} -scripting " : ''
+ $EXEC("${prefix}./shebang.js ${arg1} ${arg2}")
+ print("* ${name} via ${viajjs ? 'jjs' : 'shebang'}")
+ print($OUT.trim())
+ print($ERR.trim())
+}
+
+write('a.js', insn('A'))
+write('b.js', [pseudosheb, insn('B')])
+
+shebs.forEach(function(sheb) {
+ var shebang = "#!${jjs} ${sheb}"
+ print("<<< ${sheb} >>>")
+ write('shebang.js', [shebang, insn('S')])
+ $EXEC('chmod +x shebang.js')
+ run(false, 'noargs', '', '')
+ run(true, 'noargs', '', '')
+ run(false, 'withargs', 'a.js', '"hello world"')
+ run(true, 'withargs', 'a.js', '"hello world"')
+ $EXEC('rm shebang.js')
+})
+
+// Cleanup.
+
+$EXEC('rm a.js b.js')
+$ENV.PWD = curpwd
+Files.delete(tmpdir)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/JDK-8144221.js.EXPECTED Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,68 @@
+<<< >>>
+* noargs via shebang
+S:
+
+* noargs via jjs
+S:
+
+* withargs via shebang
+S:a.js,hello world
+
+* withargs via jjs
+S:a.js,hello world
+
+<<< --language=es6 >>>
+* noargs via shebang
+S:
+
+* noargs via jjs
+S:
+
+* withargs via shebang
+S:a.js,hello world
+
+* withargs via jjs
+S:a.js,hello world
+
+<<< --language=es6 -scripting >>>
+* noargs via shebang
+S:
+
+* noargs via jjs
+S:
+
+* withargs via shebang
+S:a.js,hello world
+
+* withargs via jjs
+S:a.js,hello world
+
+<<< -scripting a.js >>>
+* noargs via shebang
+A:
+S:
+
+* noargs via jjs
+S:
+
+* withargs via shebang
+A:
+S:
+A:
+java.io.IOException: hello world is not a file
+* withargs via jjs
+S:a.js,hello world
+
+<<< -scripting b.js >>>
+* noargs via shebang
+B:./shebang.js
+
+* noargs via jjs
+S:
+
+* withargs via shebang
+B:./shebang.js,a.js,hello world
+
+* withargs via jjs
+S:a.js,hello world
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/os-not-windows.js Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/**
+ * Test that we're not running on Windows. The test actually checks if the os.not.windows property is set and processed
+ * by runif correctly.
+ *
+ * @test
+ * @runif os.not.windows
+ * @run
+ */
+
+var os = java.lang.System.getProperty("os.name")
+
+if (os.startsWith("Windows")) {
+ throw "This test should not be run on Windows."
+}
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/test/NumberAccessTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -143,7 +143,7 @@
@Test
public void accessStaticFinalFieldLong() throws ScriptException {
e.eval("var psf_long = SharedObject.publicStaticFinalLong;");
- assertEquals(SharedObject.publicStaticFinalLong, e.get("psf_long"));
+ assertEquals(SharedObject.publicStaticFinalLong, ((Number) e.get("psf_long")).longValue());
e.eval("SharedObject.publicStaticFinalLong = 120;");
assertEquals(8333333333333L, SharedObject.publicStaticFinalLong);
}
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java Wed Jan 06 09:39:55 2016 -0500
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/test/NumberBoxingTest.java Wed Jan 06 14:54:24 2016 +0000
@@ -70,7 +70,7 @@
@Test
public void accessFieldLongBoxing() throws ScriptException {
e.eval("var p_long = o.publicLongBox;");
- assertEquals(o.publicLongBox, e.get("p_long"));
+ assertEquals(o.publicLongBox.longValue(), ((Number) e.get("p_long")).longValue());
e.eval("o.publicLongBox = 12;");
assertEquals(Long.valueOf(12), o.publicLongBox);
}
@@ -78,7 +78,7 @@
@Test
public void accessStaticFieldLongBoxing() throws ScriptException {
e.eval("var ps_long = SharedObject.publicStaticLongBox;");
- assertEquals(SharedObject.publicStaticLongBox, e.get("ps_long"));
+ assertEquals(SharedObject.publicStaticLongBox.longValue(), ((Number) e.get("ps_long")).longValue());
e.eval("SharedObject.publicStaticLongBox = 120;");
assertEquals(120L, SharedObject.publicStaticLongBox.longValue());
}
@@ -86,7 +86,7 @@
@Test
public void accessFinalFieldLongBoxing() throws ScriptException {
e.eval("var pf_long = o.publicFinalLongBox;");
- assertEquals(o.publicFinalLongBox, e.get("pf_long"));
+ assertEquals(o.publicFinalLongBox.longValue(), ((Number) e.get("pf_long")).longValue());
e.eval("o.publicFinalLongBox = 120;");
assertEquals(Long.valueOf(9377333334L), o.publicFinalLongBox);
}
@@ -94,7 +94,7 @@
@Test
public void accessStaticFinalFieldLongBoxing() throws ScriptException {
e.eval("var psf_long = SharedObject.publicStaticFinalLong;");
- assertEquals(SharedObject.publicStaticFinalLong, e.get("psf_long"));
+ assertEquals(SharedObject.publicStaticFinalLong, ((Number) e.get("psf_long")).longValue());
e.eval("SharedObject.publicStaticFinalLong = 120;");
assertEquals(8333333333333L, SharedObject.publicStaticFinalLong);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/test/models/LongProvider.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,63 @@
+/*
+ * 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 jdk.nashorn.test.models;
+
+import java.util.Arrays;
+
+/**
+ * A class that returns and receives longs.
+ */
+@SuppressWarnings("javadoc")
+public class LongProvider {
+
+ final static long[][] arrays = {
+ {1L, 2L, 3L},
+ {1L, 1L << 30, 1L << 50, 4L},
+ {1L, Long.MAX_VALUE, Long.MIN_VALUE, 4L}
+ };
+
+ public static long getLong(final String str) {
+ final long l = Long.parseLong(str);
+ checkLong(l, str);
+ return l;
+ }
+
+ public static long[] getLongArray(final int n) {
+ return arrays[n];
+ }
+
+ public static void checkLong(final long value, final String str) {
+ if (!Long.toString(value).equals(str)) {
+ throw new RuntimeException("Wrong value. Expected " + str + ", got " + value);
+ }
+ }
+
+ public static void checkLongArray(final long[] array, final int n) {
+ if (!Arrays.equals(array, arrays[n])) {
+ throw new RuntimeException("Arrays don't match: " + Arrays.toString(array) + ", " + Arrays.toString(arrays[n]));
+ }
+ }
+}
--- a/test/Makefile Wed Jan 06 09:39:55 2016 -0500
+++ b/test/Makefile Wed Jan 06 14:54:24 2016 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2010, 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
@@ -60,18 +60,28 @@
# Bring in closed test targets if present
-include $(TOPDIR)/closed/test/Makefile
+ifeq ($(TEST_JOBS), 0)
+ JDK_TEST_JOBS=$(JOBS)
+else
+ JDK_TEST_JOBS=$(TEST_JOBS)
+endif
# Test targets
langtools_% :
- @$(NO_STOPPING)$(call SUBDIR_TEST, $(LANGTOOLS_DIR), JT_JAVA=$(PRODUCT_HOME) JTREG_HOME=$(JT_HOME) TEST="$(subst langtools_,,$@)" $(subst langtools_,,$@))
+ @$(NO_STOPPING)$(call SUBDIR_TEST, $(LANGTOOLS_DIR), CONCURRENCY=$(JDK_TEST_JOBS) JT_JAVA=$(PRODUCT_HOME) JTREG_HOME=$(JT_HOME) TEST="$(subst langtools_,,$@)" $(subst langtools_,,$@))
jdk_% core_%s svc_%:
- @$(NO_STOPPING)$(call SUBDIR_TEST, $(JDK_DIR), TEST="$@" $@)
+ @$(NO_STOPPING)$(call SUBDIR_TEST, $(JDK_DIR), CONCURRENCY=$(JDK_TEST_JOBS) TEST="$@" $@)
jaxp_%:
- @$(NO_STOPPING)$(call SUBDIR_TEST, $(JAXP_DIR), TEST="$@" $@)
+ @$(NO_STOPPING)$(call SUBDIR_TEST, $(JAXP_DIR), CONCURRENCY=$(JDK_TEST_JOBS) TEST="$@" $@)
+ifeq ($(TEST_JOBS), 0)
+ HOTSPOT_TEST_JOBS=1
+else
+ HOTSPOT_TEST_JOBS=$(TEST_JOBS)
+endif
hotspot_%:
- @$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), TEST="$@" $@)
+ @$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), CONCURRENCY=$(HOTSPOT_TEST_JOBS) TEST="$@" $@)
#
# jtreg_tests
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/Asserts.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib;
+
+import java.util.Objects;
+
+/**
+ * Asserts that can be used for verifying assumptions in tests.
+ *
+ * An assertion will throw a {@link RuntimeException} if the assertion isn't true.
+ * All the asserts can be imported into a test by using a static import:
+ *
+ * <pre>
+ * {@code
+ * import static jdk.testlibrary.Asserts.*;
+ * }
+ *
+ * Always provide a message describing the assumption if the line number of the
+ * failing assertion isn't enough to understand why the assumption failed. For
+ * example, if the assertion is in a loop or in a method that is called
+ * multiple times, then the line number won't provide enough context to
+ * understand the failure.
+ * </pre>
+ */
+public class Asserts {
+
+ /**
+ * Shorthand for {@link #assertLessThan(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThan(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs) {
+ assertLessThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThan(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertLessThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLT(T lhs, T rhs, String msg) {
+ assertLessThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThan(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThan(T lhs, T rhs) {
+ assertLessThan(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>>void assertLessThan(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) < 0)) {
+ msg = Objects.toString(msg, "assertLessThan")
+ + ": expected that " + Objects.toString(lhs)
+ + " < " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThanOrEqual(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs) {
+ assertLessThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertLessThanOrEqual(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertLessThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLTE(T lhs, T rhs, String msg) {
+ assertLessThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertLessThanOrEqual(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertLessThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs) {
+ assertLessThanOrEqual(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is less than or equal to {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertLessThanOrEqual(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) <= 0)) {
+ msg = Objects.toString(msg, "assertLessThanOrEqual")
+ + ": expected that " + Objects.toString(lhs)
+ + " <= " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(Object, Object)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertEquals(Object, Object)
+ */
+ public static void assertEQ(Object lhs, Object rhs) {
+ assertEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertEquals(Object, Object, String)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertEquals(Object, Object, String)
+ */
+ public static void assertEQ(Object lhs, Object rhs, String msg) {
+ assertEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertEquals(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertEquals(Object, Object, String)
+ */
+ public static void assertEquals(Object lhs, Object rhs) {
+ assertEquals(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertEquals(Object lhs, Object rhs, String msg) {
+ if ((lhs != rhs) && ((lhs == null) || !(lhs.equals(rhs)))) {
+ msg = Objects.toString(msg, "assertEquals")
+ + ": expected " + Objects.toString(lhs)
+ + " to equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertSame(java.lang.Object, java.lang.Object, java.lang.String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertSame(Object, Object, String)
+ */
+ public static void assertSame(Object lhs, Object rhs) {
+ assertSame(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is the same as {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertSame(Object lhs, Object rhs, String msg) {
+ if (lhs != rhs) {
+ msg = Objects.toString(msg, "assertSame")
+ + ": expected " + Objects.toString(lhs)
+ + " to equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs) {
+ assertGreaterThanOrEqual(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGTE(T lhs, T rhs, String msg) {
+ assertGreaterThanOrEqual(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThanOrEqual(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThanOrEqual(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs) {
+ assertGreaterThanOrEqual(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than or equal to {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThanOrEqual(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) >= 0)) {
+ msg = Objects.toString(msg, "assertGreaterThanOrEqual")
+ + ": expected " + Objects.toString(lhs)
+ + " >= " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(Comparable, Comparable)}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertGreaterThan(Comparable, Comparable)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs) {
+ assertGreaterThan(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertGreaterThan(Comparable, Comparable, String)}.
+ *
+ * @param <T> a type
+ * @param lhs the left hand value
+ * @param rhs the right hand value
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertGreaterThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGT(T lhs, T rhs, String msg) {
+ assertGreaterThan(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertGreaterThan(Comparable, Comparable, String)} with a default message.
+ *
+ * @param <T> a type
+ * @param lhs the left hand value
+ * @param rhs the right hand value
+ * @see #assertGreaterThan(Comparable, Comparable, String)
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs) {
+ assertGreaterThan(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is greater than {@code rhs}.
+ *
+ * @param <T> a type
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static <T extends Comparable<T>> void assertGreaterThan(T lhs, T rhs, String msg) {
+ if (!(compare(lhs, rhs, msg) > 0)) {
+ msg = Objects.toString(msg, "assertGreaterThan")
+ + ": expected " + Objects.toString(lhs)
+ + " > " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(Object, Object)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertNotEquals(Object, Object)
+ */
+ public static void assertNE(Object lhs, Object rhs) {
+ assertNotEquals(lhs, rhs);
+ }
+
+ /**
+ * Shorthand for {@link #assertNotEquals(Object, Object, String)}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @see #assertNotEquals(Object, Object, String)
+ */
+ public static void assertNE(Object lhs, Object rhs, String msg) {
+ assertNotEquals(lhs, rhs, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotEquals(Object, Object, String)} with a default message.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @see #assertNotEquals(Object, Object, String)
+ */
+ public static void assertNotEquals(Object lhs, Object rhs) {
+ assertNotEquals(lhs, rhs, null);
+ }
+
+ /**
+ * Asserts that {@code lhs} is not equal to {@code rhs}.
+ *
+ * @param lhs The left hand side of the comparison.
+ * @param rhs The right hand side of the comparison.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNotEquals(Object lhs, Object rhs, String msg) {
+ if ((lhs == rhs) || (lhs != null && lhs.equals(rhs))) {
+ msg = Objects.toString(msg, "assertNotEquals")
+ + ": expected " + Objects.toString(lhs)
+ + " to not equal " + Objects.toString(rhs);
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertNull(Object, String)} with a default message.
+ *
+ * @param o The reference assumed to be null.
+ * @see #assertNull(Object, String)
+ */
+ public static void assertNull(Object o) {
+ assertNull(o, null);
+ }
+
+ /**
+ * Asserts that {@code o} is null.
+ *
+ * @param o The reference assumed to be null.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNull(Object o, String msg) {
+ assertEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertNotNull(Object, String)} with a default message.
+ *
+ * @param o The reference assumed <i>not</i> to be null,
+ * @see #assertNotNull(Object, String)
+ */
+ public static void assertNotNull(Object o) {
+ assertNotNull(o, null);
+ }
+
+ /**
+ * Asserts that {@code o} is <i>not</i> null.
+ *
+ * @param o The reference assumed <i>not</i> to be null,
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertNotNull(Object o, String msg) {
+ assertNotEquals(o, null, msg);
+ }
+
+ /**
+ * Calls {@link #assertFalse(boolean, String)} with a default message.
+ *
+ * @param value The value assumed to be false.
+ * @see #assertFalse(boolean, String)
+ */
+ public static void assertFalse(boolean value) {
+ assertFalse(value, null);
+ }
+
+ /**
+ * Asserts that {@code value} is {@code false}.
+ *
+ * @param value The value assumed to be false.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertFalse(boolean value, String msg) {
+ if (value) {
+ msg = Objects.toString(msg, "assertFalse")
+ + ": expected false, was true";
+ fail(msg);
+ }
+ }
+
+ /**
+ * Calls {@link #assertTrue(boolean, String)} with a default message.
+ *
+ * @param value The value assumed to be true.
+ * @see #assertTrue(boolean, String)
+ */
+ public static void assertTrue(boolean value) {
+ assertTrue(value, null);
+ }
+
+ /**
+ * Asserts that {@code value} is {@code true}.
+ *
+ * @param value The value assumed to be true.
+ * @param msg A description of the assumption; {@code null} for a default message.
+ * @throws RuntimeException if the assertion is not true.
+ */
+ public static void assertTrue(boolean value, String msg) {
+ if (!value) {
+ msg = Objects.toString(msg, "assertTrue")
+ + ": expected true, was false";
+ fail(msg);
+ }
+ }
+
+ private static <T extends Comparable<T>> int compare(T lhs, T rhs, String msg) {
+ if (lhs == null || rhs == null) {
+ fail(lhs, rhs, msg + ": values must be non-null:", ",");
+ }
+ return lhs.compareTo(rhs);
+ }
+
+/**
+ * Asserts that two strings are equal.
+ *
+ * If strings are not equals, then exception message
+ * will contain {@code msg} followed by list of mismatched lines.
+ *
+ * @param str1 First string to compare.
+ * @param str2 Second string to compare.
+ * @param msg A description of the assumption.
+ * @throws RuntimeException if strings are not equal.
+ */
+ public static void assertStringsEqual(String str1, String str2,
+ String msg) {
+ String lineSeparator = System.getProperty("line.separator");
+ String str1Lines[] = str1.split(lineSeparator);
+ String str2Lines[] = str2.split(lineSeparator);
+
+ int minLength = Math.min(str1Lines.length, str2Lines.length);
+ String longestStringLines[] = ((str1Lines.length == minLength) ?
+ str2Lines : str1Lines);
+
+ boolean stringsAreDifferent = false;
+
+ StringBuilder messageBuilder = new StringBuilder(msg);
+
+ messageBuilder.append("\n");
+
+ for (int line = 0; line < minLength; line++) {
+ if (!str1Lines[line].equals(str2Lines[line])) {
+ messageBuilder.append(String.
+ format("[line %d] '%s' differs " +
+ "from '%s'\n",
+ line,
+ str1Lines[line],
+ str2Lines[line]));
+ stringsAreDifferent = true;
+ }
+ }
+
+ if (minLength < longestStringLines.length) {
+ String stringName = ((longestStringLines == str1Lines) ?
+ "first" : "second");
+ messageBuilder.append(String.format("Only %s string contains " +
+ "following lines:\n",
+ stringName));
+ stringsAreDifferent = true;
+ for(int line = minLength; line < longestStringLines.length; line++) {
+ messageBuilder.append(String.
+ format("[line %d] '%s'", line,
+ longestStringLines[line]));
+ }
+ }
+
+ if (stringsAreDifferent) {
+ fail(messageBuilder.toString());
+ }
+ }
+
+ /**
+ * Returns a string formatted with a message and expected and actual values.
+ * @param lhs the actual value
+ * @param rhs the expected value
+ * @param message the actual value
+ * @param relation the asserted relationship between lhs and rhs
+ * @return a formatted string
+ */
+ public static String format(Object lhs, Object rhs, String message, String relation) {
+ StringBuilder sb = new StringBuilder(80);
+ if (message != null) {
+ sb.append(message);
+ sb.append(' ');
+ }
+ sb.append("<");
+ sb.append(Objects.toString(lhs));
+ sb.append("> ");
+ sb.append(Objects.toString(relation, ","));
+ sb.append(" <");
+ sb.append(Objects.toString(rhs));
+ sb.append(">");
+ return sb.toString();
+ }
+
+ /**
+ * Fail reports a failure with message fail.
+ *
+ * @throws RuntimeException always
+ */
+ public static void fail() {
+ fail("fail");
+ }
+
+ /**
+ * Fail reports a failure with a message.
+ * @param message for the failure
+ * @throws RuntimeException always
+ */
+ public static void fail(String message) {
+ throw new RuntimeException(message);
+ }
+
+ /**
+ * Fail reports a failure with a formatted message.
+ *
+ * @param lhs the actual value
+ * @param rhs the expected value
+ * @param message to be format before the expected and actual values
+ * @param relation the asserted relationship between lhs and rhs
+ * @throws RuntimeException always
+ */
+ public static void fail(Object lhs, Object rhs, String message, String relation) {
+ throw new RuntimeException(format(lhs, rhs, message, relation));
+ }
+
+ /**
+ * Fail reports a failure with a message and a cause.
+ * @param message to be format before the expected and actual values
+ * @param cause the exception that caused this failure
+ * @throws RuntimeException always
+ */
+ public static void fail(String message, Throwable cause) {
+ throw new RuntimeException(message, cause);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/JDKToolFinder.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib;
+
+import java.io.FileNotFoundException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public final class JDKToolFinder {
+
+ private JDKToolFinder() {
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite)
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getJDKTool(String tool) {
+
+ // First try to find the executable in test.jdk
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+
+ }
+
+ // Now see if it's available in compile.jdk
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Failed to find " + tool +
+ ", looked in test.jdk (" + System.getProperty("test.jdk") +
+ ") and compile.jdk (" + System.getProperty("compile.jdk") + ")");
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code compile.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getCompileJDKTool(String tool) {
+ try {
+ return getTool(tool, "compile.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Returns the full path to an executable in jdk/bin based on System
+ * property {@code test.jdk}
+ *
+ * @return Full path to an executable in jdk/bin
+ */
+ public static String getTestJDKTool(String tool) {
+ try {
+ return getTool(tool, "test.jdk");
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String getTool(String tool, String property) throws FileNotFoundException {
+ String jdkPath = System.getProperty(property);
+
+ if (jdkPath == null) {
+ throw new RuntimeException(
+ "System property '" + property + "' not set. This property is normally set by jtreg. "
+ + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'.");
+ }
+
+ Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : ""));
+
+ Path jdkTool = Paths.get(jdkPath, toolName.toString());
+ if (!jdkTool.toFile().exists()) {
+ throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath());
+ }
+
+ return jdkTool.toAbsolutePath().toString();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/JDKToolLauncher.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import jdk.test.lib.process.*;
+
+/**
+ * A utility for constructing command lines for starting JDK tool processes.
+ *
+ * The JDKToolLauncher can in particular be combined with a
+ * java.lang.ProcessBuilder to easily run a JDK tool. For example, the following
+ * code run {@code jmap -heap} against a process with GC logging turned on for
+ * the {@code jmap} process:
+ *
+ * <pre>
+ * {@code
+ * JDKToolLauncher jmap = JDKToolLauncher.create("jmap")
+ * .addVMArg("-XX:+PrintGC");
+ * .addVMArg("-XX:+PrintGCDetails")
+ * .addToolArg("-heap")
+ * .addToolArg(pid);
+ * ProcessBuilder pb = new ProcessBuilder(jmap.getCommand());
+ * Process p = pb.start();
+ * }
+ * </pre>
+ */
+public class JDKToolLauncher {
+ private final String executable;
+ private final List<String> vmArgs = new ArrayList<String>();
+ private final List<String> toolArgs = new ArrayList<String>();
+
+ private JDKToolLauncher(String tool, boolean useCompilerJDK) {
+ if (useCompilerJDK) {
+ executable = JDKToolFinder.getJDKTool(tool);
+ } else {
+ executable = JDKToolFinder.getTestJDKTool(tool);
+ }
+ vmArgs.addAll(Arrays.asList(ProcessTools.getPlatformSpecificVMArgs()));
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool. Using tools path
+ * from the compiler JDK.
+ *
+ * @param tool
+ * The name of the tool
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher create(String tool) {
+ return new JDKToolLauncher(tool, true);
+ }
+
+ /**
+ * Creates a new JDKToolLauncher for the specified tool in the Tested JDK.
+ *
+ * @param tool
+ * The name of the tool
+ *
+ * @return A new JDKToolLauncher
+ */
+ public static JDKToolLauncher createUsingTestJDK(String tool) {
+ return new JDKToolLauncher(tool, false);
+ }
+
+ /**
+ * Adds an argument to the JVM running the tool.
+ *
+ * The JVM arguments are passed to the underlying JVM running the tool.
+ * Arguments will automatically be prepended with "-J".
+ *
+ * Any platform specific arguments required for running the tool are
+ * automatically added.
+ *
+ *
+ * @param arg
+ * The argument to VM running the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addVMArg(String arg) {
+ vmArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Adds an argument to the tool.
+ *
+ * @param arg
+ * The argument to the tool
+ * @return The JDKToolLauncher instance
+ */
+ public JDKToolLauncher addToolArg(String arg) {
+ toolArgs.add(arg);
+ return this;
+ }
+
+ /**
+ * Returns the command that can be used for running the tool.
+ *
+ * @return An array whose elements are the arguments of the command.
+ */
+ public String[] getCommand() {
+ List<String> command = new ArrayList<String>();
+ command.add(executable);
+ // Add -J in front of all vmArgs
+ for (String arg : vmArgs) {
+ command.add("-J" + arg);
+ }
+ command.addAll(toolArgs);
+ return command.toArray(new String[command.size()]);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/Platform.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib;
+
+import java.util.regex.Pattern;
+
+public class Platform {
+ private static final String osName = System.getProperty("os.name");
+ private static final String dataModel = System.getProperty("sun.arch.data.model");
+ private static final String vmVersion = System.getProperty("java.vm.version");
+ private static final String javaVersion = System.getProperty("java.version");
+ private static final String osArch = System.getProperty("os.arch");
+ private static final String vmName = System.getProperty("java.vm.name");
+ private static final String userName = System.getProperty("user.name");
+ private static final String compiler = System.getProperty("sun.management.compiler");
+
+ public static boolean isClient() {
+ return vmName.endsWith(" Client VM");
+ }
+
+ public static boolean isServer() {
+ return vmName.endsWith(" Server VM");
+ }
+
+ public static boolean isGraal() {
+ return vmName.endsWith(" Graal VM");
+ }
+
+ public static boolean isZero() {
+ return vmName.endsWith(" Zero VM");
+ }
+
+ public static boolean isMinimal() {
+ return vmName.endsWith(" Minimal VM");
+ }
+
+ public static boolean isEmbedded() {
+ return vmName.contains("Embedded");
+ }
+
+ public static boolean isTieredSupported() {
+ return compiler.contains("Tiered Compilers");
+ }
+
+ public static boolean is32bit() {
+ return dataModel.equals("32");
+ }
+
+ public static boolean is64bit() {
+ return dataModel.equals("64");
+ }
+
+ public static boolean isAix() {
+ return isOs("aix");
+ }
+
+ public static boolean isLinux() {
+ return isOs("linux");
+ }
+
+ public static boolean isOSX() {
+ return isOs("mac");
+ }
+
+ public static boolean isSolaris() {
+ return isOs("sunos");
+ }
+
+ public static boolean isWindows() {
+ return isOs("win");
+ }
+
+ private static boolean isOs(String osname) {
+ return osName.toLowerCase().startsWith(osname.toLowerCase());
+ }
+
+ public static String getOsName() {
+ return osName;
+ }
+
+ public static boolean isDebugBuild() {
+ return (vmVersion.toLowerCase().contains("debug") ||
+ javaVersion.toLowerCase().contains("debug"));
+ }
+
+ public static String getVMVersion() {
+ return vmVersion;
+ }
+
+ // Returns true for sparc and sparcv9.
+ public static boolean isSparc() {
+ return isArch("sparc.*");
+ }
+
+ public static boolean isARM() {
+ return isArch("arm.*");
+ }
+
+ public static boolean isPPC() {
+ return isArch("ppc.*");
+ }
+
+ public static boolean isX86() {
+ // On Linux it's 'i386', Windows 'x86' without '_64' suffix.
+ return isArch("(i386)|(x86(?!_64))");
+ }
+
+ public static boolean isX64() {
+ // On OSX it's 'x86_64' and on other (Linux, Windows and Solaris) platforms it's 'amd64'
+ return isArch("(amd64)|(x86_64)");
+ }
+
+ public static boolean isAArch64() {
+ return isArch("aarch64");
+ }
+
+ private static boolean isArch(String archnameRE) {
+ return Pattern.compile(archnameRE, Pattern.CASE_INSENSITIVE)
+ .matcher(osArch)
+ .matches();
+ }
+
+ public static String getOsArch() {
+ return osArch;
+ }
+
+ /**
+ * Return a boolean for whether we expect to be able to attach
+ * the SA to our own processes on this system.
+ */
+ public static boolean shouldSAAttach() throws Exception {
+
+ if (isAix()) {
+ return false; // SA not implemented.
+ } else if (isLinux()) {
+ return canPtraceAttachLinux();
+ } else if (isOSX()) {
+ return canAttachOSX();
+ } else {
+ // Other platforms expected to work:
+ return true;
+ }
+ }
+
+ /**
+ * On Linux, first check the SELinux boolean "deny_ptrace" and return false
+ * as we expect to be denied if that is "1". Then expect permission to attach
+ * if we are root, so return true. Then return false for an expected denial
+ * if "ptrace_scope" is 1, and true otherwise.
+ */
+ public static boolean canPtraceAttachLinux() throws Exception {
+
+ // SELinux deny_ptrace:
+ String deny_ptrace = Utils.fileAsString("/sys/fs/selinux/booleans/deny_ptrace");
+ if (deny_ptrace != null && deny_ptrace.contains("1")) {
+ // ptrace will be denied:
+ return false;
+ }
+
+ // YAMA enhanced security ptrace_scope:
+ // 0 - a process can PTRACE_ATTACH to any other process running under the same uid
+ // 1 - restricted ptrace: a process must be a children of the inferior or user is root
+ // 2 - only processes with CAP_SYS_PTRACE may use ptrace or user is root
+ // 3 - no attach: no processes may use ptrace with PTRACE_ATTACH
+ String ptrace_scope = Utils.fileAsString("/proc/sys/kernel/yama/ptrace_scope");
+ if (ptrace_scope != null) {
+ if (ptrace_scope.startsWith("3")) {
+ return false;
+ }
+ if (!userName.equals("root") && !ptrace_scope.startsWith("0")) {
+ // ptrace will be denied:
+ return false;
+ }
+ }
+ // Otherwise expect to be permitted:
+ return true;
+ }
+
+ /**
+ * On OSX, expect permission to attach only if we are root.
+ */
+ public static boolean canAttachOSX() throws Exception {
+ return userName.equals("root");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/Utils.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,640 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.MalformedURLException;
+import java.net.ServerSocket;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.net.UnknownHostException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.function.BooleanSupplier;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import sun.misc.Unsafe;
+
+import jdk.test.lib.process.*;
+import static jdk.test.lib.Asserts.assertTrue;
+
+/**
+ * Common library for various test helper functions.
+ */
+public final class Utils {
+
+ /**
+ * Returns the value of 'test.class.path' system property.
+ */
+ public static final String TEST_CLASS_PATH = System.getProperty("test.class.path", ".");
+
+ /**
+ * Returns the sequence used by operating system to separate lines.
+ */
+ public static final String NEW_LINE = System.getProperty("line.separator");
+
+ /**
+ * Returns the value of 'test.vm.opts' system property.
+ */
+ public static final String VM_OPTIONS = System.getProperty("test.vm.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.java.opts' system property.
+ */
+ public static final String JAVA_OPTIONS = System.getProperty("test.java.opts", "").trim();
+
+ /**
+ * Returns the value of 'test.src' system property.
+ */
+ public static final String TEST_SRC = System.getProperty("test.src", "").trim();
+
+ private static Unsafe unsafe = null;
+
+ /**
+ * Defines property name for seed value.
+ */
+ public static final String SEED_PROPERTY_NAME = "jdk.test.lib.random.seed";
+
+ /* (non-javadoc)
+ * Random generator with (or without) predefined seed. Depends on
+ * "jdk.test.lib.random.seed" property value.
+ */
+ private static volatile Random RANDOM_GENERATOR;
+
+ /**
+ * Contains the seed value used for {@link java.util.Random} creation.
+ */
+ public static final long SEED = Long.getLong(SEED_PROPERTY_NAME, new Random().nextLong());
+ /**
+ * Returns the value of 'test.timeout.factor' system property
+ * converted to {@code double}.
+ */
+ public static final double TIMEOUT_FACTOR;
+ static {
+ String toFactor = System.getProperty("test.timeout.factor", "1.0");
+ TIMEOUT_FACTOR = Double.parseDouble(toFactor);
+ }
+
+ /**
+ * Returns the value of JTREG default test timeout in milliseconds
+ * converted to {@code long}.
+ */
+ public static final long DEFAULT_TEST_TIMEOUT = TimeUnit.SECONDS.toMillis(120);
+
+ private Utils() {
+ // Private constructor to prevent class instantiation
+ }
+
+ /**
+ * Returns the list of VM options.
+ *
+ * @return List of VM options
+ */
+ public static List<String> getVmOptions() {
+ return Arrays.asList(safeSplitString(VM_OPTIONS));
+ }
+
+ /**
+ * Returns the list of VM options with -J prefix.
+ *
+ * @return The list of VM options with -J prefix
+ */
+ public static List<String> getForwardVmOptions() {
+ String[] opts = safeSplitString(VM_OPTIONS);
+ for (int i = 0; i < opts.length; i++) {
+ opts[i] = "-J" + opts[i];
+ }
+ return Arrays.asList(opts);
+ }
+
+ /**
+ * Returns the default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+ * @return An array of options, or an empty array if no options.
+ */
+ public static String[] getTestJavaOpts() {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, safeSplitString(VM_OPTIONS));
+ Collections.addAll(opts, safeSplitString(JAVA_OPTIONS));
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Combines given arguments with default JTReg arguments for a jvm running a test.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts
+ * @return The combination of JTReg test java options and user args.
+ */
+ public static String[] addTestJavaOpts(String... userArgs) {
+ List<String> opts = new ArrayList<String>();
+ Collections.addAll(opts, getTestJavaOpts());
+ Collections.addAll(opts, userArgs);
+ return opts.toArray(new String[0]);
+ }
+
+ /**
+ * Removes any options specifying which GC to use, for example "-XX:+UseG1GC".
+ * Removes any options matching: -XX:(+/-)Use*GC
+ * Used when a test need to set its own GC version. Then any
+ * GC specified by the framework must first be removed.
+ * @return A copy of given opts with all GC options removed.
+ */
+ private static final Pattern useGcPattern = Pattern.compile(
+ "(?:\\-XX\\:[\\+\\-]Use.+GC)"
+ + "|(?:\\-Xconcgc)");
+ public static List<String> removeGcOpts(List<String> opts) {
+ List<String> optsWithoutGC = new ArrayList<String>();
+ for (String opt : opts) {
+ if (useGcPattern.matcher(opt).matches()) {
+ System.out.println("removeGcOpts: removed " + opt);
+ } else {
+ optsWithoutGC.add(opt);
+ }
+ }
+ return optsWithoutGC;
+ }
+
+ /**
+ * Returns the default JTReg arguments for a jvm running a test without
+ * options that matches regular expressions in {@code filters}.
+ * This is the combination of JTReg arguments test.vm.opts and test.java.opts.
+ * @param filters Regular expressions used to filter out options.
+ * @return An array of options, or an empty array if no options.
+ */
+ public static String[] getFilteredTestJavaOpts(String... filters) {
+ String options[] = getTestJavaOpts();
+
+ if (filters.length == 0) {
+ return options;
+ }
+
+ List<String> filteredOptions = new ArrayList<String>(options.length);
+ Pattern patterns[] = new Pattern[filters.length];
+ for (int i = 0; i < filters.length; i++) {
+ patterns[i] = Pattern.compile(filters[i]);
+ }
+
+ for (String option : options) {
+ boolean matched = false;
+ for (int i = 0; i < patterns.length && !matched; i++) {
+ Matcher matcher = patterns[i].matcher(option);
+ matched = matcher.find();
+ }
+ if (!matched) {
+ filteredOptions.add(option);
+ }
+ }
+
+ return filteredOptions.toArray(new String[filteredOptions.size()]);
+ }
+
+ /**
+ * Splits a string by white space.
+ * Works like String.split(), but returns an empty array
+ * if the string is null or empty.
+ */
+ private static String[] safeSplitString(String s) {
+ if (s == null || s.trim().isEmpty()) {
+ return new String[] {};
+ }
+ return s.trim().split("\\s+");
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString();
+ }
+
+ /**
+ * Returns the free port on the local host.
+ * The function will spin until a valid port number is found.
+ *
+ * @return The port number
+ * @throws InterruptedException if any thread has interrupted the current thread
+ * @throws IOException if an I/O error occurs when opening the socket
+ */
+ public static int getFreePort() throws InterruptedException, IOException {
+ int port = -1;
+
+ while (port <= 0) {
+ Thread.sleep(100);
+
+ ServerSocket serverSocket = null;
+ try {
+ serverSocket = new ServerSocket(0);
+ port = serverSocket.getLocalPort();
+ } finally {
+ serverSocket.close();
+ }
+ }
+
+ return port;
+ }
+
+ /**
+ * Returns the name of the local host.
+ *
+ * @return The host name
+ * @throws UnknownHostException if IP address of a host could not be determined
+ */
+ public static String getHostname() throws UnknownHostException {
+ InetAddress inetAddress = InetAddress.getLocalHost();
+ String hostName = inetAddress.getHostName();
+
+ assertTrue((hostName != null && !hostName.isEmpty()),
+ "Cannot get hostname");
+
+ return hostName;
+ }
+
+ /**
+ * Uses "jcmd -l" to search for a jvm pid. This function will wait
+ * forever (until jtreg timeout) for the pid to be found.
+ * @param key Regular expression to search for
+ * @return The found pid.
+ */
+ public static int waitForJvmPid(String key) throws Throwable {
+ final long iterationSleepMillis = 250;
+ System.out.println("waitForJvmPid: Waiting for key '" + key + "'");
+ System.out.flush();
+ while (true) {
+ int pid = tryFindJvmPid(key);
+ if (pid >= 0) {
+ return pid;
+ }
+ Thread.sleep(iterationSleepMillis);
+ }
+ }
+
+ /**
+ * Searches for a jvm pid in the output from "jcmd -l".
+ *
+ * Example output from jcmd is:
+ * 12498 sun.tools.jcmd.JCmd -l
+ * 12254 /tmp/jdk8/tl/jdk/JTwork/classes/com/sun/tools/attach/Application.jar
+ *
+ * @param key A regular expression to search for.
+ * @return The found pid, or -1 if not found.
+ * @throws Exception If multiple matching jvms are found.
+ */
+ public static int tryFindJvmPid(String key) throws Throwable {
+ OutputAnalyzer output = null;
+ try {
+ JDKToolLauncher jcmdLauncher = JDKToolLauncher.create("jcmd");
+ jcmdLauncher.addToolArg("-l");
+ output = ProcessTools.executeProcess(jcmdLauncher.getCommand());
+ output.shouldHaveExitValue(0);
+
+ // Search for a line starting with numbers (pid), follwed by the key.
+ Pattern pattern = Pattern.compile("([0-9]+)\\s.*(" + key + ").*\\r?\\n");
+ Matcher matcher = pattern.matcher(output.getStdout());
+
+ int pid = -1;
+ if (matcher.find()) {
+ pid = Integer.parseInt(matcher.group(1));
+ System.out.println("findJvmPid.pid: " + pid);
+ if (matcher.find()) {
+ throw new Exception("Found multiple JVM pids for key: " + key);
+ }
+ }
+ return pid;
+ } catch (Throwable t) {
+ System.out.println(String.format("Utils.findJvmPid(%s) failed: %s", key, t));
+ throw t;
+ }
+ }
+
+ /**
+ * Adjusts the provided timeout value for the TIMEOUT_FACTOR
+ * @param tOut the timeout value to be adjusted
+ * @return The timeout value adjusted for the value of "test.timeout.factor"
+ * system property
+ */
+ public static long adjustTimeout(long tOut) {
+ return Math.round(tOut * Utils.TIMEOUT_FACTOR);
+ }
+
+ /**
+ * Return the contents of the named file as a single String,
+ * or null if not found.
+ * @param filename name of the file to read
+ * @return String contents of file, or null if file not found.
+ * @throws IOException
+ * if an I/O error occurs reading from the file or a malformed or
+ * unmappable byte sequence is read
+ */
+ public static String fileAsString(String filename) throws IOException {
+ Path filePath = Paths.get(filename);
+ if (!Files.exists(filePath)) return null;
+ return new String(Files.readAllBytes(filePath));
+ }
+
+ /**
+ * @return Unsafe instance.
+ */
+ public static synchronized Unsafe getUnsafe() {
+ if (unsafe == null) {
+ try {
+ Field f = Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ unsafe = (Unsafe) f.get(null);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new RuntimeException("Unable to get Unsafe instance.", e);
+ }
+ }
+ return unsafe;
+ }
+ private static final char[] hexArray = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /**
+ * Returns hex view of byte array
+ *
+ * @param bytes byte array to process
+ * @return Space separated hexadecimal string representation of bytes
+ */
+
+ public static String toHexString(byte[] bytes) {
+ char[] hexView = new char[bytes.length * 3];
+ int i = 0;
+ for (byte b : bytes) {
+ hexView[i++] = hexArray[(b >> 4) & 0x0F];
+ hexView[i++] = hexArray[b & 0x0F];
+ hexView[i++] = ' ';
+ }
+ return new String(hexView);
+ }
+
+ /**
+ * Returns {@link java.util.Random} generator initialized with particular seed.
+ * The seed could be provided via system property {@link Utils#SEED_PROPERTY_NAME}
+ * In case no seed is provided, the method uses a random number.
+ * The used seed printed to stdout.
+ * @return {@link java.util.Random} generator with particular seed.
+ */
+ public static Random getRandomInstance() {
+ if (RANDOM_GENERATOR == null) {
+ synchronized (Utils.class) {
+ if (RANDOM_GENERATOR == null) {
+ RANDOM_GENERATOR = new Random(SEED);
+ System.out.printf("For random generator using seed: %d%n", SEED);
+ System.out.printf("To re-run test with same seed value please add \"-D%s=%d\" to command line.%n", SEED_PROPERTY_NAME, SEED);
+ }
+ }
+ }
+ return RANDOM_GENERATOR;
+ }
+
+ /**
+ * Returns random element of non empty collection
+ *
+ * @param <T> a type of collection element
+ * @param collection collection of elements
+ * @return random element of collection
+ * @throws IllegalArgumentException if collection is empty
+ */
+ public static <T> T getRandomElement(Collection<T> collection)
+ throws IllegalArgumentException {
+ if (collection.isEmpty()) {
+ throw new IllegalArgumentException("Empty collection");
+ }
+ Random random = getRandomInstance();
+ int elementIndex = 1 + random.nextInt(collection.size() - 1);
+ Iterator<T> iterator = collection.iterator();
+ while (--elementIndex != 0) {
+ iterator.next();
+ }
+ return iterator.next();
+ }
+
+ /**
+ * Wait for condition to be true
+ *
+ * @param condition, a condition to wait for
+ */
+ public static final void waitForCondition(BooleanSupplier condition) {
+ waitForCondition(condition, -1L, 100L);
+ }
+
+ /**
+ * Wait until timeout for condition to be true
+ *
+ * @param condition, a condition to wait for
+ * @param timeout a time in milliseconds to wait for condition to be true
+ * specifying -1 will wait forever
+ * @return condition value, to determine if wait was successful
+ */
+ public static final boolean waitForCondition(BooleanSupplier condition,
+ long timeout) {
+ return waitForCondition(condition, timeout, 100L);
+ }
+
+ /**
+ * Wait until timeout for condition to be true for specified time
+ *
+ * @param condition, a condition to wait for
+ * @param timeout a time in milliseconds to wait for condition to be true,
+ * specifying -1 will wait forever
+ * @param sleepTime a time to sleep value in milliseconds
+ * @return condition value, to determine if wait was successful
+ */
+ public static final boolean waitForCondition(BooleanSupplier condition,
+ long timeout, long sleepTime) {
+ long startTime = System.currentTimeMillis();
+ while (!(condition.getAsBoolean() || (timeout != -1L
+ && ((System.currentTimeMillis() - startTime) > timeout)))) {
+ try {
+ Thread.sleep(sleepTime);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new Error(e);
+ }
+ }
+ return condition.getAsBoolean();
+ }
+
+ /**
+ * Interface same as java.lang.Runnable but with
+ * method {@code run()} able to throw any Throwable.
+ */
+ public static interface ThrowingRunnable {
+ void run() throws Throwable;
+ }
+
+ /**
+ * Filters out an exception that may be thrown by the given
+ * test according to the given filter.
+ *
+ * @param test - method that is invoked and checked for exception.
+ * @param filter - function that checks if the thrown exception matches
+ * criteria given in the filter's implementation.
+ * @return - exception that matches the filter if it has been thrown or
+ * {@code null} otherwise.
+ * @throws Throwable - if test has thrown an exception that does not
+ * match the filter.
+ */
+ public static Throwable filterException(ThrowingRunnable test,
+ Function<Throwable, Boolean> filter) throws Throwable {
+ try {
+ test.run();
+ } catch (Throwable t) {
+ if (filter.apply(t)) {
+ return t;
+ } else {
+ throw t;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Ensures a requested class is loaded
+ * @param aClass class to load
+ */
+ public static void ensureClassIsLoaded(Class<?> aClass) {
+ if (aClass == null) {
+ throw new Error("Requested null class");
+ }
+ try {
+ Class.forName(aClass.getName(), /* initialize = */ true,
+ ClassLoader.getSystemClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new Error("Class not found", e);
+ }
+ }
+ /**
+ * @param parent a class loader to be the parent for the returned one
+ * @return an UrlClassLoader with urls made of the 'test.class.path' jtreg
+ * property and with the given parent
+ */
+ public static URLClassLoader getTestClassPathURLClassLoader(ClassLoader parent) {
+ URL[] urls = Arrays.stream(TEST_CLASS_PATH.split(File.pathSeparator))
+ .map(Paths::get)
+ .map(Path::toUri)
+ .map(x -> {
+ try {
+ return x.toURL();
+ } catch (MalformedURLException ex) {
+ throw new Error("Test issue. JTREG property"
+ + " 'test.class.path'"
+ + " is not defined correctly", ex);
+ }
+ }).toArray(URL[]::new);
+ return new URLClassLoader(urls, parent);
+ }
+
+ /**
+ * Runs runnable and checks that it throws expected exception. If exceptionException is null it means
+ * that we expect no exception to be thrown.
+ * @param runnable what we run
+ * @param expectedException expected exception
+ */
+ public static void runAndCheckException(Runnable runnable, Class<? extends Throwable> expectedException) {
+ runAndCheckException(runnable, t -> {
+ if (t == null) {
+ if (expectedException != null) {
+ throw new AssertionError("Didn't get expected exception " + expectedException.getSimpleName());
+ }
+ } else {
+ String message = "Got unexpected exception " + t.getClass().getSimpleName();
+ if (expectedException == null) {
+ throw new AssertionError(message, t);
+ } else if (!expectedException.isAssignableFrom(t.getClass())) {
+ message += " instead of " + expectedException.getSimpleName();
+ throw new AssertionError(message, t);
+ }
+ }
+ });
+ }
+
+ /**
+ * Runs runnable and makes some checks to ensure that it throws expected exception.
+ * @param runnable what we run
+ * @param checkException a consumer which checks that we got expected exception and raises a new exception otherwise
+ */
+ public static void runAndCheckException(Runnable runnable, Consumer<Throwable> checkException) {
+ try {
+ runnable.run();
+ checkException.accept(null);
+ } catch (Throwable t) {
+ checkException.accept(t);
+ }
+ }
+
+ /**
+ * Converts to VM type signature
+ *
+ * @param type Java type to convert
+ * @return string representation of VM type
+ */
+ public static String toJVMTypeSignature(Class<?> type) {
+ if (type.isPrimitive()) {
+ if (type == boolean.class) {
+ return "Z";
+ } else if (type == byte.class) {
+ return "B";
+ } else if (type == char.class) {
+ return "C";
+ } else if (type == double.class) {
+ return "D";
+ } else if (type == float.class) {
+ return "F";
+ } else if (type == int.class) {
+ return "I";
+ } else if (type == long.class) {
+ return "J";
+ } else if (type == short.class) {
+ return "S";
+ } else if (type == void.class) {
+ return "V";
+ } else {
+ throw new Error("Unsupported type: " + type);
+ }
+ }
+ String result = type.getName().replaceAll("\\.", "/");
+ if (!type.isArray()) {
+ return "L" + result + ";";
+ }
+ return result;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/process/OutputAnalyzer.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib.process;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public final class OutputAnalyzer {
+
+ private final String stdout;
+ private final String stderr;
+ private final int exitValue;
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output and exit
+ * value from a Process
+ *
+ * @param process Process to analyze
+ * @throws IOException If an I/O error occurs.
+ */
+ public OutputAnalyzer(Process process) throws IOException {
+ OutputBuffer output = ProcessTools.getOutput(process);
+ exitValue = process.exitValue();
+ this.stdout = output.getStdout();
+ this.stderr = output.getStderr();
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param buf String buffer to analyze
+ */
+ public OutputAnalyzer(String buf) {
+ this(buf, buf);
+ }
+
+ /**
+ * Create an OutputAnalyzer, a utility class for verifying output
+ *
+ * @param stdout stdout buffer to analyze
+ * @param stderr stderr buffer to analyze
+ */
+ public OutputAnalyzer(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ exitValue = -1;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stdout was not empty
+ */
+ public void stdoutShouldBeEmpty() {
+ if (!getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was not empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is empty
+ *
+ * @throws RuntimeException
+ * If stderr was not empty
+ */
+ public void stderrShouldBeEmpty() {
+ if (!getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was not empty");
+ }
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stdout was empty
+ */
+ public void stdoutShouldNotBeEmpty() {
+ if (getStdout().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stdout was empty");
+ }
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer is not empty
+ *
+ * @throws RuntimeException
+ * If stderr was empty
+ */
+ public void stderrShouldNotBeEmpty() {
+ if (getStderr().isEmpty()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("stderr was empty");
+ }
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer shouldContain(String expectedString) {
+ if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stdoutShouldContain(String expectedString) {
+ if (!stdout.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer contains the string
+ *
+ * @param expectedString String that buffer should contain
+ * @throws RuntimeException If the string was not found
+ */
+ public OutputAnalyzer stderrShouldContain(String expectedString) {
+ if (!stderr.contains(expectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer shouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
+ if (stdout.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer does not contain the string
+ *
+ * @param expectedString String that the buffer should not contain
+ * @throws RuntimeException If the string was found
+ */
+ public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
+ if (stderr.contains(notExpectedString)) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer matches
+ * the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer shouldMatch(String pattern) {
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout/stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stdoutShouldMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer matches the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was not found
+ */
+ public OutputAnalyzer stderrShouldMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (!matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' missing from stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout and stderr contents of output buffer does not
+ * match the pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer shouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout: '" + matcher.group() + "' \n");
+ }
+ matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr: '" + matcher.group() + "' \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stdout contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stdout \n");
+ }
+ return this;
+ }
+
+ /**
+ * Verify that the stderr contents of output buffer does not match the
+ * pattern
+ *
+ * @param pattern
+ * @throws RuntimeException If the pattern was found
+ */
+ public OutputAnalyzer stderrShouldNotMatch(String pattern) {
+ Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ if (matcher.find()) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("'" + pattern
+ + "' found in stderr \n");
+ }
+ return this;
+ }
+
+ /**
+ * Get the captured group of the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @param group The group to capture
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern, int group) {
+ Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+ Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+ if (stderrMatcher.find()) {
+ return stderrMatcher.group(group);
+ }
+ if (stdoutMatcher.find()) {
+ return stdoutMatcher.group(group);
+ }
+ return null;
+ }
+
+ /**
+ * Get the first string matching the pattern.
+ * stderr is searched before stdout.
+ *
+ * @param pattern The multi-line pattern to match
+ * @return The matched string or null if no match was found
+ */
+ public String firstMatch(String pattern) {
+ return firstMatch(pattern, 0);
+ }
+
+ /**
+ * Verify the exit value of the process
+ *
+ * @param expectedExitValue Expected exit value from process
+ * @throws RuntimeException If the exit value from the process did not match the expected value
+ */
+ public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
+ if (getExitValue() != expectedExitValue) {
+ reportDiagnosticSummary();
+ throw new RuntimeException("Expected to get exit value of ["
+ + expectedExitValue + "]\n");
+ }
+ return this;
+ }
+
+
+ /**
+ * Report summary that will help to diagnose the problem
+ * Currently includes:
+ * - standard input produced by the process under test
+ * - standard output
+ * - exit code
+ * Note: the command line is printed by the ProcessTools
+ */
+ private void reportDiagnosticSummary() {
+ String msg =
+ " stdout: [" + stdout + "];\n" +
+ " stderr: [" + stderr + "]\n" +
+ " exitValue = " + getExitValue() + "\n";
+
+ System.err.println(msg);
+ }
+
+
+ /**
+ * Get the contents of the output buffer (stdout and stderr)
+ *
+ * @return Content of the output buffer
+ */
+ public String getOutput() {
+ return stdout + stderr;
+ }
+
+ /**
+ * Get the contents of the stdout buffer
+ *
+ * @return Content of the stdout buffer
+ */
+ public String getStdout() {
+ return stdout;
+ }
+
+ /**
+ * Get the contents of the stderr buffer
+ *
+ * @return Content of the stderr buffer
+ */
+ public String getStderr() {
+ return stderr;
+ }
+
+ /**
+ * Get the process exit value
+ *
+ * @return Process exit value
+ */
+ public int getExitValue() {
+ return exitValue;
+ }
+
+ /**
+ * Get the contents of the output buffer (stdout and stderr) as list of strings.
+ * Output will be split by newlines.
+ *
+ * @return Contents of the output buffer as list of strings
+ */
+ public List<String> asLines() {
+ return asLines(getOutput());
+ }
+
+ private List<String> asLines(String buffer) {
+ return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/process/OutputBuffer.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib.process;
+
+public class OutputBuffer {
+ private final String stdout;
+ private final String stderr;
+
+ /**
+ * Create an OutputBuffer, a class for storing and managing stdout and stderr
+ * results separately
+ *
+ * @param stdout stdout result
+ * @param stderr stderr result
+ */
+ public OutputBuffer(String stdout, String stderr) {
+ this.stdout = stdout;
+ this.stderr = stderr;
+ }
+
+ /**
+ * Returns the stdout result
+ *
+ * @return stdout result
+ */
+ public String getStdout() {
+ return stdout;
+ }
+
+ /**
+ * Returns the stderr result
+ *
+ * @return stderr result
+ */
+ public String getStderr() {
+ return stderr;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/process/ProcessTools.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,590 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib.process;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.function.Predicate;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Platform;
+import jdk.test.lib.Utils;
+
+public final class ProcessTools {
+ private static final class LineForwarder extends StreamPumper.LinePump {
+ private final PrintStream ps;
+ private final String prefix;
+ LineForwarder(String prefix, PrintStream os) {
+ this.ps = os;
+ this.prefix = prefix;
+ }
+ @Override
+ protected void processLine(String line) {
+ ps.println("[" + prefix + "] " + line);
+ }
+ }
+
+ private ProcessTools() {
+ }
+
+ /**
+ * Pumps stdout and stderr from running the process into a String.
+ *
+ * @param processHandler ProcessHandler to run.
+ * @return Output from process.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static OutputBuffer getOutput(ProcessBuilder processBuilder) throws IOException {
+ return getOutput(processBuilder.start());
+ }
+
+ /**
+ * Pumps stdout and stderr the running process into a String.
+ *
+ * @param process Process to pump.
+ * @return Output from process.
+ * @throws IOException If an I/O error occurs.
+ */
+ public static OutputBuffer getOutput(Process process) throws IOException {
+ ByteArrayOutputStream stderrBuffer = new ByteArrayOutputStream();
+ ByteArrayOutputStream stdoutBuffer = new ByteArrayOutputStream();
+ StreamPumper outPumper = new StreamPumper(process.getInputStream(), stdoutBuffer);
+ StreamPumper errPumper = new StreamPumper(process.getErrorStream(), stderrBuffer);
+ Thread outPumperThread = new Thread(outPumper);
+ Thread errPumperThread = new Thread(errPumper);
+
+ outPumperThread.setDaemon(true);
+ errPumperThread.setDaemon(true);
+
+ outPumperThread.start();
+ errPumperThread.start();
+
+ try {
+ process.waitFor();
+ outPumperThread.join();
+ errPumperThread.join();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return null;
+ }
+
+ return new OutputBuffer(stdoutBuffer.toString(), stderrBuffer.toString());
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @return Returns the initialized process
+ * @throws IOException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder)
+ throws IOException {
+ return startProcess(name, processBuilder, (Consumer<String>)null);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>It is possible to monitor the in-streams via the provided {@code consumer}
+ * @param name The process name
+ * @param consumer {@linkplain Consumer} instance to process the in-streams
+ * @param processBuilder The process builder
+ * @return Returns the initialized process
+ * @throws IOException
+ */
+ @SuppressWarnings("overloads")
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ Consumer<String> consumer)
+ throws IOException {
+ try {
+ return startProcess(name, processBuilder, consumer, null, -1, TimeUnit.NANOSECONDS);
+ } catch (InterruptedException | TimeoutException e) {
+ // will never happen
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
+ * @param unit The timeout {@linkplain TimeUnit}
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Predicate<String> linePredicate,
+ long timeout,
+ TimeUnit unit)
+ throws IOException, InterruptedException, TimeoutException {
+ return startProcess(name, processBuilder, null, linePredicate, timeout, unit);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT and monitor the
+ * in-streams via the provided {@linkplain Consumer}
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param lineConsumer The {@linkplain Consumer} the lines will be forwarded to
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @param timeout The timeout for the warmup waiting; -1 = no wait; 0 = wait forever
+ * @param unit The timeout {@linkplain TimeUnit}
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Consumer<String> lineConsumer,
+ final Predicate<String> linePredicate,
+ long timeout,
+ TimeUnit unit)
+ throws IOException, InterruptedException, TimeoutException {
+ System.out.println("["+name+"]:" + processBuilder.command().stream().collect(Collectors.joining(" ")));
+ Process p = processBuilder.start();
+ StreamPumper stdout = new StreamPumper(p.getInputStream());
+ StreamPumper stderr = new StreamPumper(p.getErrorStream());
+
+ stdout.addPump(new LineForwarder(name, System.out));
+ stderr.addPump(new LineForwarder(name, System.err));
+ if (lineConsumer != null) {
+ StreamPumper.LinePump pump = new StreamPumper.LinePump() {
+ @Override
+ protected void processLine(String line) {
+ lineConsumer.accept(line);
+ }
+ };
+ stdout.addPump(pump);
+ stderr.addPump(pump);
+ }
+
+
+ CountDownLatch latch = new CountDownLatch(1);
+ if (linePredicate != null) {
+ StreamPumper.LinePump pump = new StreamPumper.LinePump() {
+ @Override
+ protected void processLine(String line) {
+ if (latch.getCount() > 0 && linePredicate.test(line)) {
+ latch.countDown();
+ }
+ }
+ };
+ stdout.addPump(pump);
+ stderr.addPump(pump);
+ } else {
+ latch.countDown();
+ }
+ final Future<Void> stdoutTask = stdout.process();
+ final Future<Void> stderrTask = stderr.process();
+
+ try {
+ if (timeout > -1) {
+ if (timeout == 0) {
+ latch.await();
+ } else {
+ if (!latch.await(Utils.adjustTimeout(timeout), unit)) {
+ throw new TimeoutException();
+ }
+ }
+ }
+ } catch (TimeoutException | InterruptedException e) {
+ System.err.println("Failed to start a process (thread dump follows)");
+ for(Map.Entry<Thread, StackTraceElement[]> s : Thread.getAllStackTraces().entrySet()) {
+ printStack(s.getKey(), s.getValue());
+ }
+
+ if (p.isAlive()) {
+ p.destroyForcibly();
+ }
+
+ stdoutTask.cancel(true);
+ stderrTask.cancel(true);
+ throw e;
+ }
+
+ return new ProcessImpl(p, stdoutTask, stderrTask);
+ }
+
+ /**
+ * <p>Starts a process from its builder.</p>
+ * <span>The default redirects of STDOUT and STDERR are started</span>
+ * <p>
+ * It is possible to wait for the process to get to a warmed-up state
+ * via {@linkplain Predicate} condition on the STDOUT. The warm-up will
+ * wait indefinitely.
+ * </p>
+ * @param name The process name
+ * @param processBuilder The process builder
+ * @param linePredicate The {@linkplain Predicate} to use on the STDOUT
+ * Used to determine the moment the target app is
+ * properly warmed-up.
+ * It can be null - in that case the warmup is skipped.
+ * @return Returns the initialized {@linkplain Process}
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws TimeoutException
+ */
+ @SuppressWarnings("overloads")
+ public static Process startProcess(String name,
+ ProcessBuilder processBuilder,
+ final Predicate<String> linePredicate)
+ throws IOException, InterruptedException, TimeoutException {
+ return startProcess(name, processBuilder, linePredicate, 0, TimeUnit.SECONDS);
+ }
+
+ /**
+ * Get the process id of the current running Java process
+ *
+ * @return Process id
+ */
+ public static long getProcessId() throws Exception {
+ return ProcessHandle.current().getPid();
+ }
+
+ /**
+ * Get platform specific VM arguments (e.g. -d64 on 64bit Solaris)
+ *
+ * @return String[] with platform specific arguments, empty if there are
+ * none
+ */
+ public static String[] getPlatformSpecificVMArgs() {
+
+ if (Platform.is64bit() && Platform.isSolaris()) {
+ return new String[] { "-d64" };
+ }
+
+ return new String[] {};
+ }
+
+
+ /**
+ * Create ProcessBuilder using the java launcher from the jdk to be tested and
+ * with any platform specific arguments prepended
+ */
+ public static ProcessBuilder createJavaProcessBuilder(String... command) throws Exception {
+ return createJavaProcessBuilder(false, command);
+ }
+
+ /**
+ * Create ProcessBuilder using the java launcher from the jdk to be tested,
+ * and with any platform specific arguments prepended.
+ *
+ * @param addTestVmAndJavaOptions If true, adds test.vm.opts and test.java.opts
+ * to the java arguments.
+ * @param command Arguments to pass to the java command.
+ * @return The ProcessBuilder instance representing the java command.
+ */
+ public static ProcessBuilder createJavaProcessBuilder(boolean addTestVmAndJavaOptions, String... command) throws Exception {
+ String javapath = JDKToolFinder.getJDKTool("java");
+
+ ArrayList<String> args = new ArrayList<>();
+ args.add(javapath);
+ Collections.addAll(args, getPlatformSpecificVMArgs());
+
+ if (addTestVmAndJavaOptions) {
+ // -cp is needed to make sure the same classpath is used whether the test is
+ // run in AgentVM mode or OtherVM mode. It was added to the hotspot version
+ // of this API as part of 8077608. However, for the jdk version it is only
+ // added when addTestVmAndJavaOptions is true in order to minimize
+ // disruption to existing JDK tests, which have yet to be tested with -cp
+ // being added. At some point -cp should always be added to be consistent
+ // with what the hotspot version does.
+ args.add("-cp");
+ args.add(System.getProperty("java.class.path"));
+ Collections.addAll(args, Utils.getTestJavaOpts());
+ }
+
+ Collections.addAll(args, command);
+
+ // Reporting
+ StringBuilder cmdLine = new StringBuilder();
+ for (String cmd : args)
+ cmdLine.append(cmd).append(' ');
+ System.out.println("Command line: [" + cmdLine.toString() + "]");
+
+ return new ProcessBuilder(args.toArray(new String[args.size()]));
+ }
+
+ private static void printStack(Thread t, StackTraceElement[] stack) {
+ System.out.println("\t" + t +
+ " stack: (length = " + stack.length + ")");
+ if (t != null) {
+ for (StackTraceElement stack1 : stack) {
+ System.out.println("\t" + stack1);
+ }
+ System.out.println();
+ }
+ }
+
+ /**
+ * Executes a test jvm process, waits for it to finish and returns the process output.
+ * The default jvm options from jtreg, test.vm.opts and test.java.opts, are added.
+ * The java from the test.jdk is used to execute the command.
+ *
+ * The command line will be like:
+ * {test.jdk}/bin/java {test.vm.opts} {test.java.opts} cmds
+ *
+ * The jvm process will have exited before this method returns.
+ *
+ * @param cmds User specifed arguments.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeTestJvm(String... cmds) throws Exception {
+ ProcessBuilder pb = createJavaProcessBuilder(Utils.addTestJavaOpts(cmds));
+ return executeProcess(pb);
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ * The process will have exited before this method returns.
+ * @param pb The ProcessBuilder to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeProcess(ProcessBuilder pb) throws Exception {
+ OutputAnalyzer output = null;
+ Process p = null;
+ boolean failed = false;
+ try {
+ p = pb.start();
+ output = new OutputAnalyzer(p);
+ p.waitFor();
+
+ return output;
+ } catch (Throwable t) {
+ if (p != null) {
+ p.destroyForcibly().waitFor();
+ }
+
+ failed = true;
+ System.out.println("executeProcess() failed: " + t);
+ throw t;
+ } finally {
+ if (failed) {
+ System.err.println(getProcessLog(pb, output));
+ }
+ }
+ }
+
+ /**
+ * Executes a process, waits for it to finish and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param cmds The command line to execute.
+ * @return The output from the process.
+ */
+ public static OutputAnalyzer executeProcess(String... cmds) throws Throwable {
+ return executeProcess(new ProcessBuilder(cmds));
+ }
+
+ /**
+ * Used to log command line, stdout, stderr and exit code from an executed process.
+ * @param pb The executed process.
+ * @param output The output from the process.
+ */
+ public static String getProcessLog(ProcessBuilder pb, OutputAnalyzer output) {
+ String stderr = output == null ? "null" : output.getStderr();
+ String stdout = output == null ? "null" : output.getStdout();
+ String exitValue = output == null ? "null": Integer.toString(output.getExitValue());
+ StringBuilder logMsg = new StringBuilder();
+ final String nl = System.getProperty("line.separator");
+ logMsg.append("--- ProcessLog ---" + nl);
+ logMsg.append("cmd: " + getCommandLine(pb) + nl);
+ logMsg.append("exitvalue: " + exitValue + nl);
+ logMsg.append("stderr: " + stderr + nl);
+ logMsg.append("stdout: " + stdout + nl);
+
+ return logMsg.toString();
+ }
+
+ /**
+ * @return The full command line for the ProcessBuilder.
+ */
+ public static String getCommandLine(ProcessBuilder pb) {
+ if (pb == null) {
+ return "null";
+ }
+ StringBuilder cmd = new StringBuilder();
+ for (String s : pb.command()) {
+ cmd.append(s).append(" ");
+ }
+ return cmd.toString().trim();
+ }
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout, and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param cmds The command line to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(String... cmds)
+ throws Throwable {
+ String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
+
+ /**
+ * Executes a process, waits for it to finish, prints the process output
+ * to stdout and returns the process output.
+ *
+ * The process will have exited before this method returns.
+ *
+ * @param pb The ProcessBuilder to execute.
+ * @return The {@linkplain OutputAnalyzer} instance wrapping the process.
+ */
+ public static OutputAnalyzer executeCommand(ProcessBuilder pb)
+ throws Throwable {
+ String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
+ System.out.println("Command line: [" + cmdLine + "]");
+ OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
+ System.out.println(analyzer.getOutput());
+ return analyzer;
+ }
+
+ private static class ProcessImpl extends Process {
+
+ private final Process p;
+ private final Future<Void> stdoutTask;
+ private final Future<Void> stderrTask;
+
+ public ProcessImpl(Process p, Future<Void> stdoutTask, Future<Void> stderrTask) {
+ this.p = p;
+ this.stdoutTask = stdoutTask;
+ this.stderrTask = stderrTask;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return p.getOutputStream();
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return p.getInputStream();
+ }
+
+ @Override
+ public InputStream getErrorStream() {
+ return p.getErrorStream();
+ }
+
+ @Override
+ public int waitFor() throws InterruptedException {
+ int rslt = p.waitFor();
+ waitForStreams();
+ return rslt;
+ }
+
+ @Override
+ public int exitValue() {
+ return p.exitValue();
+ }
+
+ @Override
+ public void destroy() {
+ p.destroy();
+ }
+
+ @Override
+ public long getPid() {
+ return p.getPid();
+ }
+
+ @Override
+ public boolean isAlive() {
+ return p.isAlive();
+ }
+
+ @Override
+ public Process destroyForcibly() {
+ return p.destroyForcibly();
+ }
+
+ @Override
+ public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException {
+ boolean rslt = p.waitFor(timeout, unit);
+ if (rslt) {
+ waitForStreams();
+ }
+ return rslt;
+ }
+
+ private void waitForStreams() throws InterruptedException {
+ try {
+ stdoutTask.get();
+ } catch (ExecutionException e) {
+ }
+ try {
+ stderrTask.get();
+ } catch (ExecutionException e) {
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lib/share/classes/jdk/test/lib/process/StreamPumper.java Wed Jan 06 14:54:24 2016 +0000
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2013, 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.
+ */
+
+package jdk.test.lib.process;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public final class StreamPumper implements Runnable {
+
+ private static final int BUF_SIZE = 256;
+
+ /**
+ * Pump will be called by the StreamPumper to process the incoming data
+ */
+ abstract public static class Pump {
+ abstract void register(StreamPumper d);
+ }
+
+ /**
+ * OutputStream -> Pump adapter
+ */
+ final public static class StreamPump extends Pump {
+ private final OutputStream out;
+ public StreamPump(OutputStream out) {
+ this.out = out;
+ }
+
+ @Override
+ void register(StreamPumper sp) {
+ sp.addOutputStream(out);
+ }
+ }
+
+ /**
+ * Used to process the incoming data line-by-line
+ */
+ abstract public static class LinePump extends Pump {
+ @Override
+ final void register(StreamPumper sp) {
+ sp.addLineProcessor(this);
+ }
+
+ abstract protected void processLine(String line);
+ }
+
+ private final InputStream in;
+ private final Set<OutputStream> outStreams = new HashSet<>();
+ private final Set<LinePump> linePumps = new HashSet<>();
+
+ private final AtomicBoolean processing = new AtomicBoolean(false);
+ private final FutureTask<Void> processingTask = new FutureTask<>(this, null);
+
+ public StreamPumper(InputStream in) {
+ this.in = in;
+ }
+
+ /**
+ * Create a StreamPumper that reads from in and writes to out.
+ *
+ * @param in The stream to read from.
+ * @param out The stream to write to.
+ */
+ public StreamPumper(InputStream in, OutputStream out) {
+ this(in);
+ this.addOutputStream(out);
+ }
+
+ /**
+ * Implements Thread.run(). Continuously read from {@code in} and write to
+ * {@code out} until {@code in} has reached end of stream. Abort on
+ * interruption. Abort on IOExceptions.
+ */
+ @Override
+ public void run() {
+ try (BufferedInputStream is = new BufferedInputStream(in)) {
+ ByteArrayOutputStream lineBos = new ByteArrayOutputStream();
+ byte[] buf = new byte[BUF_SIZE];
+ int len = 0;
+ int linelen = 0;
+
+ while ((len = is.read(buf)) > 0 && !Thread.interrupted()) {
+ for(OutputStream out : outStreams) {
+ out.write(buf, 0, len);
+ }
+ if (!linePumps.isEmpty()) {
+ int i = 0;
+ int lastcrlf = -1;
+ while (i < len) {
+ if (buf[i] == '\n' || buf[i] == '\r') {
+ int bufLinelen = i - lastcrlf - 1;
+ if (bufLinelen > 0) {
+ lineBos.write(buf, lastcrlf + 1, bufLinelen);
+ }
+ linelen += bufLinelen;
+
+ if (linelen > 0) {
+ lineBos.flush();
+ final String line = lineBos.toString();
+ linePumps.stream().forEach((lp) -> {
+ lp.processLine(line);
+ });
+ lineBos.reset();
+ linelen = 0;
+ }
+ lastcrlf = i;
+ }
+
+ i++;
+ }
+ if (lastcrlf == -1) {
+ lineBos.write(buf, 0, len);
+ linelen += len;
+ } else if (lastcrlf < len - 1) {
+ lineBos.write(buf, lastcrlf + 1, len - lastcrlf - 1);
+ linelen += len - lastcrlf - 1;
+ }
+ }
+ }
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ for(OutputStream out : outStreams) {
+ try {
+ out.flush();
+ } catch (IOException e) {}
+ }
+ try {
+ in.close();
+ } catch (IOException e) {}
+ }
+ }
+
+ final void addOutputStream(OutputStream out) {
+ outStreams.add(out);
+ }
+
+ final void addLineProcessor(LinePump lp) {
+ linePumps.add(lp);
+ }
+
+ final public StreamPumper addPump(Pump ... pump) {
+ if (processing.get()) {
+ throw new IllegalStateException("Can not modify pumper while " +
+ "processing is in progress");
+ }
+ for(Pump p : pump) {
+ p.register(this);
+ }
+ return this;
+ }
+
+ final public Future<Void> process() {
+ if (!processing.compareAndSet(false, true)) {
+ throw new IllegalStateException("Can not re-run the processing");
+ }
+ Thread t = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ processingTask.run();
+ }
+ });
+ t.setDaemon(true);
+ t.start();
+
+ return processingTask;
+ }
+}