# HG changeset patch
# User chegar
# Date 1513254512 0
# Node ID b6ff245c0db6ffc2a8998fb1157ea6bea7e28d8e
# Parent 907bddce488c9017160ae8430110d9bd300d46f3# Parent 651a95f30dfbd825ec9603a28e081102a1de53b0
http-client-branch: merge with default
diff -r 907bddce488c -r b6ff245c0db6 .hgtags
--- a/.hgtags Mon Dec 11 16:43:11 2017 +0000
+++ b/.hgtags Thu Dec 14 12:28:32 2017 +0000
@@ -459,3 +459,4 @@
a2008587c13fa05fa2dbfcb09fe987576fbedfd1 jdk-10+32
bbd692ad4fa300ecca7939ffbe3b1d5e52a28cc6 jdk-10+33
89deac44e51517841491ba86ff44aa82a5ca96b3 jdk-10+34
+d8c634b016c628622c9abbdc6bf50509e5dedbec jdk-10+35
diff -r 907bddce488c -r b6ff245c0db6 make/MacBundles.gmk
--- a/make/MacBundles.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/MacBundles.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
BUNDLE_ID := $(MACOSX_BUNDLE_ID_BASE).$(VERSION_SHORT)
BUNDLE_NAME := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_SHORT)
BUNDLE_INFO := $(MACOSX_BUNDLE_NAME_BASE) $(VERSION_STRING)
- BUNDLE_PLATFORM_VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)
+ BUNDLE_PLATFORM_VERSION := $(VERSION_FEATURE).$(VERSION_INTERIM)
BUNDLE_VERSION := $(VERSION_NUMBER)
ifeq ($(COMPANY_NAME), N/A)
BUNDLE_VENDOR := UNDEFINED
diff -r 907bddce488c -r b6ff245c0db6 make/ReleaseFile.gmk
--- a/make/ReleaseFile.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/ReleaseFile.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,9 @@
$(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
$(call info-file-item, "SOURCE", "$(strip $(SOURCE_REVISION))")
$(call info-file-item, "IMPLEMENTOR", "$(COMPANY_NAME)")
+ $(if $(VENDOR_VERSION_STRING), \
+ $(call info-file-item, "IMPLEMENTOR_VERSION", "$(VENDOR_VERSION_STRING)"))
+ $(call info-file-item, "JAVA_VERSION_DATE", "$(VERSION_DATE)")
$(call info-file-item, "OS_NAME", "$(RELEASE_FILE_OS_NAME)")
$(call info-file-item, "OS_ARCH", "$(RELEASE_FILE_OS_ARCH)")
endef
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/flags.m4
--- a/make/autoconf/flags.m4 Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/flags.m4 Thu Dec 14 12:28:32 2017 +0000
@@ -313,7 +313,7 @@
-D\"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \
-D\"JDK_VER=\$(VERSION_NUMBER)\" \
-D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \
- -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \
+ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_FEATURE)\" \
-D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\""
JVM_RCFLAGS="$JVM_RCFLAGS \
@@ -1166,7 +1166,9 @@
-I${TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \
-I${TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \
-I${TOPDIR}/src/java.base/share/native/libjava \
- -I${TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava"
+ -I${TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/libjava \
+ -I${TOPDIR}/src/hotspot/share/include \
+ -I${TOPDIR}/src/hotspot/os/${HOTSPOT_$1_OS_TYPE}/include"
# The shared libraries are compiled using the picflag.
$2CFLAGS_JDKLIB="[$]$2COMMON_CCXXFLAGS_JDK \
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/generated-configure.sh
--- a/make/autoconf/generated-configure.sh Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/generated-configure.sh Thu Dec 14 12:28:32 2017 +0000
@@ -887,6 +887,8 @@
BOOT_JDK
JAVA_CHECK
JAVAC_CHECK
+VENDOR_VERSION_STRING
+VERSION_DATE
VERSION_IS_GA
VERSION_SHORT
VERSION_STRING
@@ -896,9 +898,9 @@
VERSION_BUILD
VERSION_PRE
VERSION_PATCH
-VERSION_SECURITY
-VERSION_MINOR
-VERSION_MAJOR
+VERSION_UPDATE
+VERSION_INTERIM
+VERSION_FEATURE
MACOSX_BUNDLE_ID_BASE
MACOSX_BUNDLE_NAME_BASE
HOTSPOT_VM_DISTRO
@@ -972,7 +974,6 @@
HOTSPOT_BUILD_OS_TYPE
HOTSPOT_BUILD_OS
OPENJDK_BUILD_BUNDLE_PLATFORM
-OPENJDK_BUILD_OS_EXPORT_DIR
OPENJDK_BUILD_CPU_OSARCH
OPENJDK_BUILD_CPU_ISADIR
OPENJDK_BUILD_CPU_LEGACY_LIB
@@ -984,7 +985,6 @@
HOTSPOT_TARGET_OS
DEFINE_CROSS_COMPILE_ARCH
OPENJDK_TARGET_BUNDLE_PLATFORM
-OPENJDK_TARGET_OS_EXPORT_DIR
OPENJDK_TARGET_CPU_OSARCH
OPENJDK_TARGET_CPU_ISADIR
OPENJDK_TARGET_CPU_LEGACY_LIB
@@ -1093,6 +1093,7 @@
docdir
oldincludedir
includedir
+runstatedir
localstatedir
sharedstatedir
sysconfdir
@@ -1143,14 +1144,19 @@
with_update_version
with_user_release_suffix
with_build_number
+with_version_major
+with_version_minor
+with_version_security
with_version_string
with_version_pre
with_version_opt
with_version_build
-with_version_major
-with_version_minor
-with_version_security
+with_version_feature
+with_version_interim
+with_version_update
with_version_patch
+with_version_date
+with_vendor_version_string
with_boot_jdk
with_build_jdk
with_import_modules
@@ -1377,6 +1383,7 @@
sysconfdir='${prefix}/etc'
sharedstatedir='${prefix}/com'
localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
includedir='${prefix}/include'
oldincludedir='/usr/include'
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1629,6 +1636,15 @@
| -silent | --silent | --silen | --sile | --sil)
silent=yes ;;
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1766,7 +1782,7 @@
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
datadir sysconfdir sharedstatedir localstatedir includedir \
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir
+ libdir localedir mandir runstatedir
do
eval ac_val=\$$ac_var
# Remove trailing slashes.
@@ -1919,6 +1935,7 @@
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
--libdir=DIR object code libraries [EPREFIX/lib]
--includedir=DIR C header files [PREFIX/include]
--oldincludedir=DIR C header files for non-gcc [/usr/include]
@@ -2060,6 +2077,12 @@
compatibility and is ignored
--with-build-number Deprecated. Option is kept for backwards
compatibility and is ignored
+ --with-version-major Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-version-minor Deprecated. Option is kept for backwards
+ compatibility and is ignored
+ --with-version-security Deprecated. Option is kept for backwards
+ compatibility and is ignored
--with-version-string Set version string [calculated]
--with-version-pre Set the base part of the version 'PRE' field
(pre-release identifier) ['internal']
@@ -2067,14 +2090,17 @@
[..]
--with-version-build Set version 'BUILD' field (build number) [not
specified]
- --with-version-major Set version 'MAJOR' field (first number) [current
+ --with-version-feature Set version 'FEATURE' field (first number) [current
source value]
- --with-version-minor Set version 'MINOR' field (second number) [current
+ --with-version-interim Set version 'INTERIM' field (second number) [current
source value]
- --with-version-security Set version 'SECURITY' field (third number) [current
+ --with-version-update Set version 'UPDATE' field (third number) [current
source value]
--with-version-patch Set version 'PATCH' field (fourth number) [not
specified]
+ --with-version-date Set version date [current source value]
+ --with-vendor-version-string
+ Set vendor version string [not specified]
--with-boot-jdk path to Boot JDK (used to bootstrap build) [probed]
--with-build-jdk path to JDK of same version as is being built[the
newly built JDK]
@@ -4449,7 +4475,7 @@
#
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -5159,7 +5185,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1512479382
+DATE_WHEN_GENERATED=1513206608
###############################################################################
#
@@ -16200,13 +16226,6 @@
OPENJDK_TARGET_CPU_JLI="amd64"
fi
- if test "x$OPENJDK_TARGET_OS" = xmacosx; then
- OPENJDK_TARGET_OS_EXPORT_DIR=macosx
- else
- OPENJDK_TARGET_OS_EXPORT_DIR=${OPENJDK_TARGET_OS_TYPE}
- fi
-
-
# The new version string in JDK 9 also defined new naming of OS and ARCH for bundles
# Macosx is osx and x86_64 is x64
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
@@ -16358,13 +16377,6 @@
OPENJDK_BUILD_CPU_JLI="amd64"
fi
- if test "x$OPENJDK_BUILD_OS" = xmacosx; then
- OPENJDK_BUILD_OS_EXPORT_DIR=macosx
- else
- OPENJDK_BUILD_OS_EXPORT_DIR=${OPENJDK_BUILD_OS_TYPE}
- fi
-
-
# The new version string in JDK 9 also defined new naming of OS and ARCH for bundles
# Macosx is osx and x86_64 is x64
if test "x$OPENJDK_BUILD_OS" = xmacosx; then
@@ -25004,6 +25016,33 @@
+
+# Check whether --with-version-major was given.
+if test "${with_version_major+set}" = set; then :
+ withval=$with_version_major; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-version-major is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-version-major is deprecated and will be ignored." >&2;}
+fi
+
+
+
+
+# Check whether --with-version-minor was given.
+if test "${with_version_minor+set}" = set; then :
+ withval=$with_version_minor; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-version-minor is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-version-minor is deprecated and will be ignored." >&2;}
+fi
+
+
+
+
+# Check whether --with-version-security was given.
+if test "${with_version_security+set}" = set; then :
+ withval=$with_version_security; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-version-security is deprecated and will be ignored." >&5
+$as_echo "$as_me: WARNING: Option --with-version-security is deprecated and will be ignored." >&2;}
+fi
+
+
+
# Source the version numbers file
. $AUTOCONF_DIR/version-numbers
@@ -25032,20 +25071,20 @@
elif test "x$with_version_string" != x; then
# Additional [] needed to keep m4 from mangling shell constructs.
if [[ $with_version_string =~ ^([0-9]+)(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(-([a-zA-Z]+))?((\+)([0-9]+)?(-([-a-zA-Z0-9.]+))?)?$ ]] ; then
- VERSION_MAJOR=${BASH_REMATCH[1]}
- VERSION_MINOR=${BASH_REMATCH[3]}
- VERSION_SECURITY=${BASH_REMATCH[5]}
+ VERSION_FEATURE=${BASH_REMATCH[1]}
+ VERSION_INTERIM=${BASH_REMATCH[3]}
+ VERSION_UPDATE=${BASH_REMATCH[5]}
VERSION_PATCH=${BASH_REMATCH[7]}
VERSION_PRE=${BASH_REMATCH[9]}
version_plus_separator=${BASH_REMATCH[11]}
VERSION_BUILD=${BASH_REMATCH[12]}
VERSION_OPT=${BASH_REMATCH[14]}
# Unspecified numerical fields are interpreted as 0.
- if test "x$VERSION_MINOR" = x; then
- VERSION_MINOR=0
- fi
- if test "x$VERSION_SECURITY" = x; then
- VERSION_SECURITY=0
+ if test "x$VERSION_INTERIM" = x; then
+ VERSION_INTERIM=0
+ fi
+ if test "x$VERSION_UPDATE" = x; then
+ VERSION_UPDATE=0
fi
if test "x$VERSION_PATCH" = x; then
VERSION_PATCH=0
@@ -25174,22 +25213,22 @@
fi
-# Check whether --with-version-major was given.
-if test "${with_version_major+set}" = set; then :
- withval=$with_version_major; with_version_major_present=true
-else
- with_version_major_present=false
-fi
-
-
- if test "x$with_version_major_present" = xtrue; then
- if test "x$with_version_major" = xyes; then
- as_fn_error $? "--with-version-major must have a value" "$LINENO" 5
+# Check whether --with-version-feature was given.
+if test "${with_version_feature+set}" = set; then :
+ withval=$with_version_feature; with_version_feature_present=true
+else
+ with_version_feature_present=false
+fi
+
+
+ if test "x$with_version_feature_present" = xtrue; then
+ if test "x$with_version_feature" = xyes; then
+ as_fn_error $? "--with-version-feature must have a value" "$LINENO" 5
else
# Additional [] needed to keep m4 from mangling shell constructs.
- if ! [[ "$with_version_major" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
- as_fn_error $? "\"$with_version_major\" is not a valid numerical value for VERSION_MAJOR" "$LINENO" 5
+ if ! [[ "$with_version_feature" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
+ as_fn_error $? "\"$with_version_feature\" is not a valid numerical value for VERSION_FEATURE" "$LINENO" 5
fi
# Extract the version number without leading zeros.
cleaned_value=${BASH_REMATCH[1]}
@@ -25199,44 +25238,44 @@
fi
if test $cleaned_value -gt 255; then
- as_fn_error $? "VERSION_MAJOR is given as $with_version_major. This is greater than 255 which is not allowed." "$LINENO" 5
- fi
- if test "x$cleaned_value" != "x$with_version_major"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_MAJOR has been sanitized from '$with_version_major' to '$cleaned_value'" >&5
-$as_echo "$as_me: WARNING: Value for VERSION_MAJOR has been sanitized from '$with_version_major' to '$cleaned_value'" >&2;}
- fi
- VERSION_MAJOR=$cleaned_value
+ as_fn_error $? "VERSION_FEATURE is given as $with_version_feature. This is greater than 255 which is not allowed." "$LINENO" 5
+ fi
+ if test "x$cleaned_value" != "x$with_version_feature"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_FEATURE has been sanitized from '$with_version_feature' to '$cleaned_value'" >&5
+$as_echo "$as_me: WARNING: Value for VERSION_FEATURE has been sanitized from '$with_version_feature' to '$cleaned_value'" >&2;}
+ fi
+ VERSION_FEATURE=$cleaned_value
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is to get value from version-numbers
- VERSION_MAJOR="$DEFAULT_VERSION_MAJOR"
- fi
- fi
-
-
-# Check whether --with-version-minor was given.
-if test "${with_version_minor+set}" = set; then :
- withval=$with_version_minor; with_version_minor_present=true
-else
- with_version_minor_present=false
-fi
-
-
- if test "x$with_version_minor_present" = xtrue; then
- if test "x$with_version_minor" = xyes; then
- as_fn_error $? "--with-version-minor must have a value" "$LINENO" 5
- elif test "x$with_version_minor" = xno; then
+ VERSION_FEATURE="$DEFAULT_VERSION_FEATURE"
+ fi
+ fi
+
+
+# Check whether --with-version-interim was given.
+if test "${with_version_interim+set}" = set; then :
+ withval=$with_version_interim; with_version_interim_present=true
+else
+ with_version_interim_present=false
+fi
+
+
+ if test "x$with_version_interim_present" = xtrue; then
+ if test "x$with_version_interim" = xyes; then
+ as_fn_error $? "--with-version-interim must have a value" "$LINENO" 5
+ elif test "x$with_version_interim" = xno; then
# Interpret --without-* as empty string (i.e. 0) instead of the literal "no"
- VERSION_MINOR=0
- elif test "x$with_version_minor" = x; then
- VERSION_MINOR=0
+ VERSION_INTERIM=0
+ elif test "x$with_version_interim" = x; then
+ VERSION_INTERIM=0
else
# Additional [] needed to keep m4 from mangling shell constructs.
- if ! [[ "$with_version_minor" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
- as_fn_error $? "\"$with_version_minor\" is not a valid numerical value for VERSION_MINOR" "$LINENO" 5
+ if ! [[ "$with_version_interim" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
+ as_fn_error $? "\"$with_version_interim\" is not a valid numerical value for VERSION_INTERIM" "$LINENO" 5
fi
# Extract the version number without leading zeros.
cleaned_value=${BASH_REMATCH[1]}
@@ -25246,44 +25285,44 @@
fi
if test $cleaned_value -gt 255; then
- as_fn_error $? "VERSION_MINOR is given as $with_version_minor. This is greater than 255 which is not allowed." "$LINENO" 5
- fi
- if test "x$cleaned_value" != "x$with_version_minor"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_MINOR has been sanitized from '$with_version_minor' to '$cleaned_value'" >&5
-$as_echo "$as_me: WARNING: Value for VERSION_MINOR has been sanitized from '$with_version_minor' to '$cleaned_value'" >&2;}
- fi
- VERSION_MINOR=$cleaned_value
+ as_fn_error $? "VERSION_INTERIM is given as $with_version_interim. This is greater than 255 which is not allowed." "$LINENO" 5
+ fi
+ if test "x$cleaned_value" != "x$with_version_interim"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_INTERIM has been sanitized from '$with_version_interim' to '$cleaned_value'" >&5
+$as_echo "$as_me: WARNING: Value for VERSION_INTERIM has been sanitized from '$with_version_interim' to '$cleaned_value'" >&2;}
+ fi
+ VERSION_INTERIM=$cleaned_value
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is 0, if unspecified
- VERSION_MINOR=$DEFAULT_VERSION_MINOR
- fi
- fi
-
-
-# Check whether --with-version-security was given.
-if test "${with_version_security+set}" = set; then :
- withval=$with_version_security; with_version_security_present=true
-else
- with_version_security_present=false
-fi
-
-
- if test "x$with_version_security_present" = xtrue; then
- if test "x$with_version_security" = xyes; then
- as_fn_error $? "--with-version-security must have a value" "$LINENO" 5
- elif test "x$with_version_security" = xno; then
+ VERSION_INTERIM=$DEFAULT_VERSION_INTERIM
+ fi
+ fi
+
+
+# Check whether --with-version-update was given.
+if test "${with_version_update+set}" = set; then :
+ withval=$with_version_update; with_version_update_present=true
+else
+ with_version_update_present=false
+fi
+
+
+ if test "x$with_version_update_present" = xtrue; then
+ if test "x$with_version_update" = xyes; then
+ as_fn_error $? "--with-version-update must have a value" "$LINENO" 5
+ elif test "x$with_version_update" = xno; then
# Interpret --without-* as empty string (i.e. 0) instead of the literal "no"
- VERSION_SECURITY=0
- elif test "x$with_version_security" = x; then
- VERSION_SECURITY=0
+ VERSION_UPDATE=0
+ elif test "x$with_version_update" = x; then
+ VERSION_UPDATE=0
else
# Additional [] needed to keep m4 from mangling shell constructs.
- if ! [[ "$with_version_security" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
- as_fn_error $? "\"$with_version_security\" is not a valid numerical value for VERSION_SECURITY" "$LINENO" 5
+ if ! [[ "$with_version_update" =~ ^0*([1-9][0-9]*)|(0)$ ]] ; then
+ as_fn_error $? "\"$with_version_update\" is not a valid numerical value for VERSION_UPDATE" "$LINENO" 5
fi
# Extract the version number without leading zeros.
cleaned_value=${BASH_REMATCH[1]}
@@ -25293,19 +25332,19 @@
fi
if test $cleaned_value -gt 255; then
- as_fn_error $? "VERSION_SECURITY is given as $with_version_security. This is greater than 255 which is not allowed." "$LINENO" 5
- fi
- if test "x$cleaned_value" != "x$with_version_security"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_SECURITY has been sanitized from '$with_version_security' to '$cleaned_value'" >&5
-$as_echo "$as_me: WARNING: Value for VERSION_SECURITY has been sanitized from '$with_version_security' to '$cleaned_value'" >&2;}
- fi
- VERSION_SECURITY=$cleaned_value
+ as_fn_error $? "VERSION_UPDATE is given as $with_version_update. This is greater than 255 which is not allowed." "$LINENO" 5
+ fi
+ if test "x$cleaned_value" != "x$with_version_update"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Value for VERSION_UPDATE has been sanitized from '$with_version_update' to '$cleaned_value'" >&5
+$as_echo "$as_me: WARNING: Value for VERSION_UPDATE has been sanitized from '$with_version_update' to '$cleaned_value'" >&2;}
+ fi
+ VERSION_UPDATE=$cleaned_value
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is 0, if unspecified
- VERSION_SECURITY=$DEFAULT_VERSION_SECURITY
+ VERSION_UPDATE=$DEFAULT_VERSION_UPDATE
fi
fi
@@ -25366,7 +25405,7 @@
fi
# VERSION_NUMBER but always with exactly 4 positions, with 0 for empty positions.
- VERSION_NUMBER_FOUR_POSITIONS=$VERSION_MAJOR.$VERSION_MINOR.$VERSION_SECURITY.$VERSION_PATCH
+ VERSION_NUMBER_FOUR_POSITIONS=$VERSION_FEATURE.$VERSION_INTERIM.$VERSION_UPDATE.$VERSION_PATCH
stripped_version_number=$VERSION_NUMBER_FOUR_POSITIONS
# Strip trailing zeroes from stripped_version_number
@@ -25384,6 +25423,40 @@
# The short version string, just VERSION_NUMBER and PRE, if present.
VERSION_SHORT=$VERSION_NUMBER${VERSION_PRE:+-$VERSION_PRE}
+ # The version date
+
+# Check whether --with-version-date was given.
+if test "${with_version_date+set}" = set; then :
+ withval=$with_version_date;
+fi
+
+ if test "x$with_version_date" = xyes; then
+ as_fn_error $? "--with-version-date must have a value" "$LINENO" 5
+ elif test "x$with_version_date" != x; then
+ if ! [[ $with_version_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] ; then
+ as_fn_error $? "\"$with_version_date\" is not a valid version date" "$LINENO" 5
+ else
+ VERSION_DATE="$with_version_date"
+ fi
+ else
+ VERSION_DATE="$DEFAULT_VERSION_DATE"
+ fi
+
+ # The vendor version string, if any
+
+# Check whether --with-vendor-version-string was given.
+if test "${with_vendor_version_string+set}" = set; then :
+ withval=$with_vendor_version_string;
+fi
+
+ if test "x$with_vendor_version_string" = xyes; then
+ as_fn_error $? "--with-vendor-version-string must have a value" "$LINENO" 5
+ elif ! [[ $with_vendor_version_string =~ ^[[:graph:]]*$ ]] ; then
+ as_fn_error $? "--with--vendor-version-string contains non-graphical characters: $with_vendor_version_string" "$LINENO" 5
+ else
+ VENDOR_VERSION_STRING="$with_vendor_version_string"
+ fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for version string" >&5
$as_echo_n "checking for version string... " >&6; }
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $VERSION_STRING" >&5
@@ -25403,6 +25476,8 @@
+
+
###############################################################################
#
# Setup BootJDK, used to bootstrap the build.
@@ -50669,7 +50744,7 @@
-D\"JDK_COMPONENT=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) binary\" \
-D\"JDK_VER=\$(VERSION_NUMBER)\" \
-D\"JDK_COPYRIGHT=Copyright \xA9 $COPYRIGHT_YEAR\" \
- -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_MAJOR)\" \
+ -D\"JDK_NAME=\$(PRODUCT_NAME) \$(JDK_RC_PLATFORM_NAME) \$(VERSION_FEATURE)\" \
-D\"JDK_FVER=\$(subst .,\$(COMMA),\$(VERSION_NUMBER_FOUR_POSITIONS))\""
JVM_RCFLAGS="$JVM_RCFLAGS \
@@ -52817,7 +52892,9 @@
-I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \
-I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \
-I${TOPDIR}/src/java.base/share/native/libjava \
- -I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava"
+ -I${TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/libjava \
+ -I${TOPDIR}/src/hotspot/share/include \
+ -I${TOPDIR}/src/hotspot/os/${HOTSPOT_TARGET_OS_TYPE}/include"
# The shared libraries are compiled using the picflag.
CFLAGS_JDKLIB="$COMMON_CCXXFLAGS_JDK \
@@ -53698,7 +53775,9 @@
-I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \
-I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \
-I${TOPDIR}/src/java.base/share/native/libjava \
- -I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava"
+ -I${TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/libjava \
+ -I${TOPDIR}/src/hotspot/share/include \
+ -I${TOPDIR}/src/hotspot/os/${HOTSPOT_BUILD_OS_TYPE}/include"
# The shared libraries are compiled using the picflag.
OPENJDK_BUILD_CFLAGS_JDKLIB="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/jdk-version.m4
--- a/make/autoconf/jdk-version.m4 Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/jdk-version.m4 Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,9 @@
BASIC_DEPRECATED_ARG_WITH([update-version])
BASIC_DEPRECATED_ARG_WITH([user-release-suffix])
BASIC_DEPRECATED_ARG_WITH([build-number])
+ BASIC_DEPRECATED_ARG_WITH([version-major])
+ BASIC_DEPRECATED_ARG_WITH([version-minor])
+ BASIC_DEPRECATED_ARG_WITH([version-security])
# Source the version numbers file
. $AUTOCONF_DIR/version-numbers
@@ -87,20 +90,20 @@
elif test "x$with_version_string" != x; then
# Additional [] needed to keep m4 from mangling shell constructs.
if [ [[ $with_version_string =~ ^([0-9]+)(\.([0-9]+))?(\.([0-9]+))?(\.([0-9]+))?(-([a-zA-Z]+))?((\+)([0-9]+)?(-([-a-zA-Z0-9.]+))?)?$ ]] ]; then
- VERSION_MAJOR=${BASH_REMATCH[[1]]}
- VERSION_MINOR=${BASH_REMATCH[[3]]}
- VERSION_SECURITY=${BASH_REMATCH[[5]]}
+ VERSION_FEATURE=${BASH_REMATCH[[1]]}
+ VERSION_INTERIM=${BASH_REMATCH[[3]]}
+ VERSION_UPDATE=${BASH_REMATCH[[5]]}
VERSION_PATCH=${BASH_REMATCH[[7]]}
VERSION_PRE=${BASH_REMATCH[[9]]}
version_plus_separator=${BASH_REMATCH[[11]]}
VERSION_BUILD=${BASH_REMATCH[[12]]}
VERSION_OPT=${BASH_REMATCH[[14]]}
# Unspecified numerical fields are interpreted as 0.
- if test "x$VERSION_MINOR" = x; then
- VERSION_MINOR=0
+ if test "x$VERSION_INTERIM" = x; then
+ VERSION_INTERIM=0
fi
- if test "x$VERSION_SECURITY" = x; then
- VERSION_SECURITY=0
+ if test "x$VERSION_UPDATE" = x; then
+ VERSION_UPDATE=0
fi
if test "x$VERSION_PATCH" = x; then
VERSION_PATCH=0
@@ -191,64 +194,64 @@
fi
fi
- AC_ARG_WITH(version-major, [AS_HELP_STRING([--with-version-major],
- [Set version 'MAJOR' field (first number) @<:@current source value@:>@])],
- [with_version_major_present=true], [with_version_major_present=false])
+ AC_ARG_WITH(version-feature, [AS_HELP_STRING([--with-version-feature],
+ [Set version 'FEATURE' field (first number) @<:@current source value@:>@])],
+ [with_version_feature_present=true], [with_version_feature_present=false])
- if test "x$with_version_major_present" = xtrue; then
- if test "x$with_version_major" = xyes; then
- AC_MSG_ERROR([--with-version-major must have a value])
+ if test "x$with_version_feature_present" = xtrue; then
+ if test "x$with_version_feature" = xyes; then
+ AC_MSG_ERROR([--with-version-feature must have a value])
else
- JDKVER_CHECK_AND_SET_NUMBER(VERSION_MAJOR, $with_version_major)
+ JDKVER_CHECK_AND_SET_NUMBER(VERSION_FEATURE, $with_version_feature)
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is to get value from version-numbers
- VERSION_MAJOR="$DEFAULT_VERSION_MAJOR"
+ VERSION_FEATURE="$DEFAULT_VERSION_FEATURE"
fi
fi
- AC_ARG_WITH(version-minor, [AS_HELP_STRING([--with-version-minor],
- [Set version 'MINOR' field (second number) @<:@current source value@:>@])],
- [with_version_minor_present=true], [with_version_minor_present=false])
+ AC_ARG_WITH(version-interim, [AS_HELP_STRING([--with-version-interim],
+ [Set version 'INTERIM' field (second number) @<:@current source value@:>@])],
+ [with_version_interim_present=true], [with_version_interim_present=false])
- if test "x$with_version_minor_present" = xtrue; then
- if test "x$with_version_minor" = xyes; then
- AC_MSG_ERROR([--with-version-minor must have a value])
- elif test "x$with_version_minor" = xno; then
+ if test "x$with_version_interim_present" = xtrue; then
+ if test "x$with_version_interim" = xyes; then
+ AC_MSG_ERROR([--with-version-interim must have a value])
+ elif test "x$with_version_interim" = xno; then
# Interpret --without-* as empty string (i.e. 0) instead of the literal "no"
- VERSION_MINOR=0
- elif test "x$with_version_minor" = x; then
- VERSION_MINOR=0
+ VERSION_INTERIM=0
+ elif test "x$with_version_interim" = x; then
+ VERSION_INTERIM=0
else
- JDKVER_CHECK_AND_SET_NUMBER(VERSION_MINOR, $with_version_minor)
+ JDKVER_CHECK_AND_SET_NUMBER(VERSION_INTERIM, $with_version_interim)
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is 0, if unspecified
- VERSION_MINOR=$DEFAULT_VERSION_MINOR
+ VERSION_INTERIM=$DEFAULT_VERSION_INTERIM
fi
fi
- AC_ARG_WITH(version-security, [AS_HELP_STRING([--with-version-security],
- [Set version 'SECURITY' field (third number) @<:@current source value@:>@])],
- [with_version_security_present=true], [with_version_security_present=false])
+ AC_ARG_WITH(version-update, [AS_HELP_STRING([--with-version-update],
+ [Set version 'UPDATE' field (third number) @<:@current source value@:>@])],
+ [with_version_update_present=true], [with_version_update_present=false])
- if test "x$with_version_security_present" = xtrue; then
- if test "x$with_version_security" = xyes; then
- AC_MSG_ERROR([--with-version-security must have a value])
- elif test "x$with_version_security" = xno; then
+ if test "x$with_version_update_present" = xtrue; then
+ if test "x$with_version_update" = xyes; then
+ AC_MSG_ERROR([--with-version-update must have a value])
+ elif test "x$with_version_update" = xno; then
# Interpret --without-* as empty string (i.e. 0) instead of the literal "no"
- VERSION_SECURITY=0
- elif test "x$with_version_security" = x; then
- VERSION_SECURITY=0
+ VERSION_UPDATE=0
+ elif test "x$with_version_update" = x; then
+ VERSION_UPDATE=0
else
- JDKVER_CHECK_AND_SET_NUMBER(VERSION_SECURITY, $with_version_security)
+ JDKVER_CHECK_AND_SET_NUMBER(VERSION_UPDATE, $with_version_update)
fi
else
if test "x$NO_DEFAULT_VERSION_PARTS" != xtrue; then
# Default is 0, if unspecified
- VERSION_SECURITY=$DEFAULT_VERSION_SECURITY
+ VERSION_UPDATE=$DEFAULT_VERSION_UPDATE
fi
fi
@@ -284,7 +287,7 @@
fi
# VERSION_NUMBER but always with exactly 4 positions, with 0 for empty positions.
- VERSION_NUMBER_FOUR_POSITIONS=$VERSION_MAJOR.$VERSION_MINOR.$VERSION_SECURITY.$VERSION_PATCH
+ VERSION_NUMBER_FOUR_POSITIONS=$VERSION_FEATURE.$VERSION_INTERIM.$VERSION_UPDATE.$VERSION_PATCH
stripped_version_number=$VERSION_NUMBER_FOUR_POSITIONS
# Strip trailing zeroes from stripped_version_number
@@ -302,12 +305,38 @@
# The short version string, just VERSION_NUMBER and PRE, if present.
VERSION_SHORT=$VERSION_NUMBER${VERSION_PRE:+-$VERSION_PRE}
+ # The version date
+ AC_ARG_WITH(version-date, [AS_HELP_STRING([--with-version-date],
+ [Set version date @<:@current source value@:>@])])
+ if test "x$with_version_date" = xyes; then
+ AC_MSG_ERROR([--with-version-date must have a value])
+ elif test "x$with_version_date" != x; then
+ if [ ! [[ $with_version_date =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] ]; then
+ AC_MSG_ERROR(["$with_version_date" is not a valid version date])
+ else
+ VERSION_DATE="$with_version_date"
+ fi
+ else
+ VERSION_DATE="$DEFAULT_VERSION_DATE"
+ fi
+
+ # The vendor version string, if any
+ AC_ARG_WITH(vendor-version-string, [AS_HELP_STRING([--with-vendor-version-string],
+ [Set vendor version string @<:@not specified@:>@])])
+ if test "x$with_vendor_version_string" = xyes; then
+ AC_MSG_ERROR([--with-vendor-version-string must have a value])
+ elif [ ! [[ $with_vendor_version_string =~ ^[[:graph:]]*$ ]] ]; then
+ AC_MSG_ERROR([--with--vendor-version-string contains non-graphical characters: $with_vendor_version_string])
+ else
+ VENDOR_VERSION_STRING="$with_vendor_version_string"
+ fi
+
AC_MSG_CHECKING([for version string])
AC_MSG_RESULT([$VERSION_STRING])
- AC_SUBST(VERSION_MAJOR)
- AC_SUBST(VERSION_MINOR)
- AC_SUBST(VERSION_SECURITY)
+ AC_SUBST(VERSION_FEATURE)
+ AC_SUBST(VERSION_INTERIM)
+ AC_SUBST(VERSION_UPDATE)
AC_SUBST(VERSION_PATCH)
AC_SUBST(VERSION_PRE)
AC_SUBST(VERSION_BUILD)
@@ -317,4 +346,6 @@
AC_SUBST(VERSION_STRING)
AC_SUBST(VERSION_SHORT)
AC_SUBST(VERSION_IS_GA)
+ AC_SUBST(VERSION_DATE)
+ AC_SUBST(VENDOR_VERSION_STRING)
])
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/platform.m4
--- a/make/autoconf/platform.m4 Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/platform.m4 Thu Dec 14 12:28:32 2017 +0000
@@ -388,13 +388,6 @@
OPENJDK_$1_CPU_JLI="amd64"
fi
- if test "x$OPENJDK_$1_OS" = xmacosx; then
- OPENJDK_$1_OS_EXPORT_DIR=macosx
- else
- OPENJDK_$1_OS_EXPORT_DIR=${OPENJDK_$1_OS_TYPE}
- fi
- AC_SUBST(OPENJDK_$1_OS_EXPORT_DIR)
-
# The new version string in JDK 9 also defined new naming of OS and ARCH for bundles
# Macosx is osx and x86_64 is x64
if test "x$OPENJDK_$1_OS" = xmacosx; then
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/spec.gmk.in
--- a/make/autoconf/spec.gmk.in Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/spec.gmk.in Thu Dec 14 12:28:32 2017 +0000
@@ -78,7 +78,6 @@
OPENJDK_TARGET_CPU_LEGACY:=@OPENJDK_TARGET_CPU_LEGACY@
OPENJDK_TARGET_CPU_LEGACY_LIB:=@OPENJDK_TARGET_CPU_LEGACY_LIB@
OPENJDK_TARGET_CPU_OSARCH:=@OPENJDK_TARGET_CPU_OSARCH@
-OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@
HOTSPOT_TARGET_OS := @HOTSPOT_TARGET_OS@
HOTSPOT_TARGET_OS_TYPE := @HOTSPOT_TARGET_OS_TYPE@
@@ -144,10 +143,9 @@
## Building blocks of the version string
# First three version numbers, with well-specified meanings (numerical)
-VERSION_MAJOR := @VERSION_MAJOR@
-VERSION_MINOR := @VERSION_MINOR@
-VERSION_SECURITY := @VERSION_SECURITY@
-# Optional fourth element for use by OpenJDK consumers (numerical)
+VERSION_FEATURE := @VERSION_FEATURE@
+VERSION_INTERIM := @VERSION_INTERIM@
+VERSION_UPDATE := @VERSION_UPDATE@
VERSION_PATCH := @VERSION_PATCH@
# The pre-release identifier (string)
VERSION_PRE := @VERSION_PRE@
@@ -165,17 +163,23 @@
VERSION_STRING := @VERSION_STRING@
# The short version string, without trailing zeroes and just PRE, if present.
VERSION_SHORT := @VERSION_SHORT@
-# The Java specification version. It usually equals the major version number.
-VERSION_SPECIFICATION := @VERSION_MAJOR@
+# The Java specification version. It usually equals the feature version number.
+VERSION_SPECIFICATION := @VERSION_FEATURE@
# A GA version is defined by the PRE string being empty. Rather than testing for
# that, this variable defines it with true/false.
VERSION_IS_GA := @VERSION_IS_GA@
+# Version date
+VERSION_DATE := @VERSION_DATE@
+
+# Vendor version string
+VENDOR_VERSION_STRING := @VENDOR_VERSION_STRING@
+
# Convenience CFLAGS settings for passing version information into native programs.
VERSION_CFLAGS := \
- -DVERSION_MAJOR=$(VERSION_MAJOR) \
- -DVERSION_MINOR=$(VERSION_MINOR) \
- -DVERSION_SECURITY=$(VERSION_SECURITY) \
+ -DVERSION_FEATURE=$(VERSION_FEATURE) \
+ -DVERSION_INTERIM=$(VERSION_INTERIM) \
+ -DVERSION_UPDATE=$(VERSION_UPDATE) \
-DVERSION_PATCH=$(VERSION_PATCH) \
-DVERSION_PRE='"$(VERSION_PRE)"' \
-DVERSION_BUILD=$(VERSION_BUILD) \
@@ -184,6 +188,8 @@
-DVERSION_STRING='"$(VERSION_STRING)"' \
-DVERSION_SHORT='"$(VERSION_SHORT)"' \
-DVERSION_SPECIFICATION='"$(VERSION_SPECIFICATION)"' \
+ -DVERSION_DATE='"$(VERSION_DATE)"' \
+ -DVENDOR_VERSION_STRING='"$(VENDOR_VERSION_STRING)"' \
#
# Platform naming variables
diff -r 907bddce488c -r b6ff245c0db6 make/autoconf/version-numbers
--- a/make/autoconf/version-numbers Mon Dec 11 16:43:11 2017 +0000
+++ b/make/autoconf/version-numbers Thu Dec 14 12:28:32 2017 +0000
@@ -25,10 +25,11 @@
# Default version numbers to use unless overridden by configure
-DEFAULT_VERSION_MAJOR=10
-DEFAULT_VERSION_MINOR=0
-DEFAULT_VERSION_SECURITY=0
+DEFAULT_VERSION_FEATURE=10
+DEFAULT_VERSION_INTERIM=0
+DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0
+DEFAULT_VERSION_DATE=2018-03-20
LAUNCHER_NAME=openjdk
PRODUCT_NAME=OpenJDK
diff -r 907bddce488c -r b6ff245c0db6 make/conf/jib-profiles.js
--- a/make/conf/jib-profiles.js Mon Dec 11 16:43:11 2017 +0000
+++ b/make/conf/jib-profiles.js Thu Dec 14 12:28:32 2017 +0000
@@ -662,6 +662,16 @@
}
});
+ // For open profiles, the non-debug jdk bundles, need an "open" prefix on the
+ // remote bundle names, forming the word "openjdk". See JDK-8188789.
+ common.main_profile_names.forEach(function (name) {
+ var openName = name + common.open_suffix;
+ profiles[openName].artifacts["jdk"].remote = replaceAll(
+ "\/jdk-", "/openjdk-",
+ replaceAll("\/\\1", "/open\\1",
+ profiles[openName].artifacts["jdk"].remote));
+ });
+
// Profiles used to run tests. Used in JPRT and Mach 5.
var testOnlyProfiles = {
"run-test-jprt": {
@@ -1040,17 +1050,17 @@
* Constructs the numeric version string from reading the
* make/autoconf/version-numbers file and removing all trailing ".0".
*
- * @param major Override major version
- * @param minor Override minor version
- * @param security Override security version
+ * @param feature Override feature version
+ * @param interim Override interim version
+ * @param update Override update version
* @param patch Override patch version
* @returns {String} The numeric version string
*/
-var getVersion = function (major, minor, security, patch) {
+var getVersion = function (feature, interim, update, patch) {
var version_numbers = getVersionNumbers();
- var version = (major != null ? major : version_numbers.get("DEFAULT_VERSION_MAJOR"))
- + "." + (minor != null ? minor : version_numbers.get("DEFAULT_VERSION_MINOR"))
- + "." + (security != null ? security : version_numbers.get("DEFAULT_VERSION_SECURITY"))
+ var version = (feature != null ? feature : version_numbers.get("DEFAULT_VERSION_FEATURE"))
+ + "." + (interim != null ? interim : version_numbers.get("DEFAULT_VERSION_INTERIM"))
+ + "." + (update != null ? update : version_numbers.get("DEFAULT_VERSION_UPDATE"))
+ "." + (patch != null ? patch : version_numbers.get("DEFAULT_VERSION_PATCH"));
while (version.match(".*\\.0$")) {
version = version.substring(0, version.length - 2);
diff -r 907bddce488c -r b6ff245c0db6 make/copy/Copy-java.base.gmk
--- a/make/copy/Copy-java.base.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/copy/Copy-java.base.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -28,24 +28,6 @@
$(eval $(call IncludeCustomExtension, copy/Copy-java.base.gmk))
################################################################################
-#
-# Copy exported header files to outputdir.
-#
-TARGETS += \
- $(INCLUDE_DST_DIR)/jni.h \
- $(INCLUDE_DST_DIR)/jvmticmlr.h \
- $(INCLUDE_DST_DIR)/classfile_constants.h \
- $(INCLUDE_DST_OS_DIR)/jni_md.h \
- #
-
-$(INCLUDE_DST_DIR)/%.h: $(TOPDIR)/src/java.base/share/native/include/%.h
- $(call install-file)
-
-$(INCLUDE_DST_OS_DIR)/%.h: \
- $(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include/%.h
- $(call install-file)
-
-################################################################################
ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),)
diff -r 907bddce488c -r b6ff245c0db6 make/copy/Copy-java.desktop.gmk
--- a/make/copy/Copy-java.desktop.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/copy/Copy-java.desktop.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -29,20 +29,6 @@
################################################################################
-TARGETS += \
- $(INCLUDE_DST_DIR)/jawt.h \
- $(INCLUDE_DST_OS_DIR)/jawt_md.h \
- #
-
-$(INCLUDE_DST_DIR)/%.h: $(TOPDIR)/src/java.desktop/share/native/include/%.h
- $(call install-file)
-
-$(INCLUDE_DST_OS_DIR)/%.h: \
- $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h
- $(call install-file)
-
-################################################################################
-
ifneq ($(FREETYPE_BUNDLE_LIB_PATH), )
# We need to bundle the freetype library, so it will be available at runtime
# as well as link time.
diff -r 907bddce488c -r b6ff245c0db6 make/copy/Copy-jdk.accessibility.gmk
--- a/make/copy/Copy-jdk.accessibility.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/copy/Copy-jdk.accessibility.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2104, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,19 +23,7 @@
# questions.
#
-include CopyCommon.gmk
-
################################################################################
+# Include CopyCommon.gmk to get exported header files to be properly copied.
-ifeq ($(OPENJDK_TARGET_OS), windows)
- TARGETS += $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCallbacks.h \
- $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgeCalls.h \
- $(INCLUDE_DST_OS_DIR)/bridge/AccessBridgePackages.h
-
- $(INCLUDE_DST_OS_DIR)/bridge/%: \
- $(TOPDIR)/src/jdk.accessibility/windows/native/include/bridge/%
- $(install-file)
-
-endif
-
-################################################################################
+include CopyCommon.gmk
diff -r 907bddce488c -r b6ff245c0db6 make/copy/Copy-jdk.jdwp.agent.gmk
--- a/make/copy/Copy-jdk.jdwp.agent.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/copy/Copy-jdk.jdwp.agent.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,13 +23,7 @@
# questions.
#
-include CopyCommon.gmk
-
################################################################################
+# Include CopyCommon.gmk to get exported header files to be properly copied.
-TARGETS := $(INCLUDE_DST_DIR)/jdwpTransport.h
-
-$(INCLUDE_DST_DIR)/%.h: $(TOPDIR)/src/jdk.jdwp.agent/share/native/include/%.h
- $(call install-file)
-
-################################################################################
+include CopyCommon.gmk
diff -r 907bddce488c -r b6ff245c0db6 make/copy/CopyCommon.gmk
--- a/make/copy/CopyCommon.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/copy/CopyCommon.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -23,15 +23,48 @@
# questions.
#
-INCLUDE_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_include/$(MODULE)
LIB_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_libs/$(MODULE)
CONF_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_conf/$(MODULE)
LEGAL_DST_DIR := $(SUPPORT_OUTPUTDIR)/modules_legal/$(MODULE)
-INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/$(OPENJDK_TARGET_OS)
+################################################################################
+#
+# Copy exported include headers files to output directory, if present.
+#
+
+INCLUDE_TARGET_DIR := $(SUPPORT_OUTPUTDIR)/modules_include/$(MODULE)
+INCLUDE_SOURCE_DIR := $(TOPDIR)/src/$(MODULE)/share/native/include
+ifneq ($(wildcard $(INCLUDE_SOURCE_DIR)/*), )
+ $(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE, \
+ SRC := $(INCLUDE_SOURCE_DIR), \
+ DEST := $(INCLUDE_TARGET_DIR), \
+ FILES := $(shell $(FIND) $(INCLUDE_SOURCE_DIR) -type f), \
+ ))
+
+ TARGETS += $(COPY_EXPORTED_INCLUDE)
+endif
+
+# For historical reasons, the OS include directories have odd names.
+INCLUDE_TARGET_OS_SUBDIR := $(OPENJDK_TARGET_OS)
ifeq ($(OPENJDK_TARGET_OS), windows)
- INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/win32
+ INCLUDE_TARGET_OS_SUBDIR := win32
else ifeq ($(OPENJDK_TARGET_OS), macosx)
- INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/darwin
+ INCLUDE_TARGET_OS_SUBDIR := darwin
+endif
+
+# Use the most specific of OS and OS_TYPE.
+INCLUDE_SOURCE_OS_DIR := $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS)/native/include
+ifeq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), )
+ INCLUDE_SOURCE_OS_DIR := $(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/include
endif
+
+ifneq ($(wildcard $(INCLUDE_SOURCE_OS_DIR)/*), )
+ $(eval $(call SetupCopyFiles, COPY_EXPORTED_INCLUDE_OS, \
+ SRC := $(INCLUDE_SOURCE_OS_DIR), \
+ DEST := $(INCLUDE_TARGET_DIR)/$(INCLUDE_TARGET_OS_SUBDIR), \
+ FILES := $(shell $(FIND) $(INCLUDE_SOURCE_OS_DIR) -type f), \
+ ))
+
+ TARGETS += $(COPY_EXPORTED_INCLUDE_OS)
+endif
diff -r 907bddce488c -r b6ff245c0db6 make/gensrc/GensrcMisc.gmk
--- a/make/gensrc/GensrcMisc.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/gensrc/GensrcMisc.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -38,7 +38,9 @@
@@VERSION_NUMBER@@ => $(VERSION_NUMBER) ; \
@@VERSION_PRE@@ => $(VERSION_PRE) ; \
@@VERSION_BUILD@@ => $(VERSION_BUILD) ; \
- @@VERSION_OPT@@ => $(VERSION_OPT), \
+ @@VERSION_OPT@@ => $(VERSION_OPT) ; \
+ @@VERSION_DATE@@ => $(VERSION_DATE) ; \
+ @@VENDOR_VERSION_STRING@@ => $(VENDOR_VERSION_STRING), \
))
GENSRC_JAVA_BASE += $(BUILD_VERSION_JAVA)
diff -r 907bddce488c -r b6ff245c0db6 make/gensrc/GensrcX11Wrappers.gmk
--- a/make/gensrc/GensrcX11Wrappers.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/gensrc/GensrcX11Wrappers.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -92,8 +92,10 @@
endif
SIZER_CFLAGS := \
+ -I${TOPDIR}/src/hotspot/share/include \
+ -I${TOPDIR}/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \
-I$(TOPDIR)/src/java.base/share/native/include \
- -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include \
+ -I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \
-I$(TOPDIR)/src/java.base/share/native/libjava \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjava \
-I$(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt \
diff -r 907bddce488c -r b6ff245c0db6 make/hotspot/lib/CompileJvm.gmk
--- a/make/hotspot/lib/CompileJvm.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/hotspot/lib/CompileJvm.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -57,9 +57,10 @@
$(patsubst %,-I%,$(filter-out $(JVM_VARIANT_OUTPUTDIR)/gensrc/%, $(JVM_SRC_DIRS))) \
-I$(JVM_VARIANT_OUTPUTDIR)/gensrc \
-I$(TOPDIR)/src/hotspot/share/precompiled \
+ -I$(TOPDIR)/src/hotspot/share/include \
+ -I$(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include \
-I$(TOPDIR)/src/java.base/share/native/include \
-I$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/include \
- -I$(TOPDIR)/src/java.management/share/native/include \
-I$(TOPDIR)/src/java.base/share/native/libjimage \
#
diff -r 907bddce488c -r b6ff245c0db6 make/hotspot/lib/CompileLibjsig.gmk
--- a/make/hotspot/lib/CompileLibjsig.gmk Mon Dec 11 16:43:11 2017 +0000
+++ b/make/hotspot/lib/CompileLibjsig.gmk Thu Dec 14 12:28:32 2017 +0000
@@ -57,7 +57,7 @@
endif
else ifeq ($(OPENJDK_TARGET_OS), solaris)
- LIBJSIG_CFLAGS := -m64 -KPIC -mt -I $(TOPDIR)/src/java.base/unix/native/include
+ LIBJSIG_CFLAGS := -m64 -KPIC -mt -I $(TOPDIR)/src/hotspot/os/$(HOTSPOT_TARGET_OS_TYPE)/include
LIBJSIG_LDFLAGS := -m64 -mt -xnolib
LIBJSIG_LIBS := $(LIBDL)
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java
--- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java Thu Dec 14 12:28:32 2017 +0000
@@ -37,6 +37,7 @@
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXNotRecognizedException;
@@ -52,21 +53,32 @@
static final String LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldml.dtd";
static final String SPPL_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlSupplemental.dtd";
+ static final String BCP47_LDML_DTD_SYSTEM_ID = "http://www.unicode.org/cldr/dtd/2.0/ldmlBCP47.dtd";
+
private static String CLDR_BASE = "../CLDR/21.0.1/";
static String LOCAL_LDML_DTD;
static String LOCAL_SPPL_LDML_DTD;
+ static String LOCAL_BCP47_LDML_DTD;
private static String SOURCE_FILE_DIR;
private static String SPPL_SOURCE_FILE;
private static String NUMBERING_SOURCE_FILE;
private static String METAZONES_SOURCE_FILE;
private static String LIKELYSUBTAGS_SOURCE_FILE;
+ private static String TIMEZONE_SOURCE_FILE;
static String DESTINATION_DIR = "build/gensrc";
static final String LOCALE_NAME_PREFIX = "locale.displayname.";
+ static final String LOCALE_SEPARATOR = LOCALE_NAME_PREFIX + "separator";
+ static final String LOCALE_KEYTYPE = LOCALE_NAME_PREFIX + "keytype";
+ static final String LOCALE_KEY_PREFIX = LOCALE_NAME_PREFIX + "key.";
+ static final String LOCALE_TYPE_PREFIX = LOCALE_NAME_PREFIX + "type.";
+ static final String LOCALE_TYPE_PREFIX_CA = LOCALE_TYPE_PREFIX + "ca.";
static final String CURRENCY_SYMBOL_PREFIX = "currency.symbol.";
static final String CURRENCY_NAME_PREFIX = "currency.displayname.";
static final String CALENDAR_NAME_PREFIX = "calendarname.";
+ static final String CALENDAR_FIRSTDAY_PREFIX = "firstDay.";
+ static final String CALENDAR_MINDAYS_PREFIX = "minDays.";
static final String TIMEZONE_ID_PREFIX = "timezone.id.";
static final String ZONE_NAME_PREFIX = "timezone.displayname.";
static final String METAZONE_ID_PREFIX = "metazone.id.";
@@ -76,6 +88,7 @@
private static LikelySubtagsParseHandler handlerLikelySubtags;
static NumberingSystemsParseHandler handlerNumbering;
static MetaZonesParseHandler handlerMetaZones;
+ static TimeZoneParseHandler handlerTimeZone;
private static BundleGenerator bundleGenerator;
// java.base module related
@@ -201,11 +214,13 @@
// Set up path names
LOCAL_LDML_DTD = CLDR_BASE + "/dtd/ldml.dtd";
LOCAL_SPPL_LDML_DTD = CLDR_BASE + "/dtd/ldmlSupplemental.dtd";
+ LOCAL_BCP47_LDML_DTD = CLDR_BASE + "/dtd/ldmlBCP47.dtd";
SOURCE_FILE_DIR = CLDR_BASE + "/main";
SPPL_SOURCE_FILE = CLDR_BASE + "/supplemental/supplementalData.xml";
LIKELYSUBTAGS_SOURCE_FILE = CLDR_BASE + "/supplemental/likelySubtags.xml";
NUMBERING_SOURCE_FILE = CLDR_BASE + "/supplemental/numberingSystems.xml";
METAZONES_SOURCE_FILE = CLDR_BASE + "/supplemental/metaZones.xml";
+ TIMEZONE_SOURCE_FILE = CLDR_BASE + "/bcp47/timezone.xml";
if (BASE_LOCALES.isEmpty()) {
setupBaseLocales("en-US");
@@ -215,10 +230,10 @@
// Parse data independent of locales
parseSupplemental();
+ parseBCP47();
List bundles = readBundleList();
convertBundles(bundles);
- convertBundles(addedBundles);
}
private static void usage() {
@@ -314,34 +329,19 @@
}
private static final Map> cldrBundles = new HashMap<>();
- // this list will contain additional bundles to be generated for Region dependent Data.
- private static List addedBundles = new ArrayList<>();
private static Map> metaInfo = new HashMap<>();
static {
// For generating information on supported locales.
- metaInfo.put("LocaleNames", new TreeSet<>());
- metaInfo.put("CurrencyNames", new TreeSet<>());
- metaInfo.put("TimeZoneNames", new TreeSet<>());
- metaInfo.put("CalendarData", new TreeSet<>());
- metaInfo.put("FormatData", new TreeSet<>());
metaInfo.put("AvailableLocales", new TreeSet<>());
}
-
- private static Set calendarDataFields = Set.of("firstDayOfWeek", "minimalDaysInFirstWeek");
-
static Map getCLDRBundle(String id) throws Exception {
Map bundle = cldrBundles.get(id);
if (bundle != null) {
return bundle;
}
- SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setValidating(true);
- SAXParser parser = factory.newSAXParser();
- enableFileAccess(parser);
- LDMLParseHandler handler = new LDMLParseHandler(id);
File file = new File(SOURCE_FILE_DIR + File.separator + id + ".xml");
if (!file.exists()) {
// Skip if the file doesn't exist.
@@ -349,14 +349,15 @@
}
info("..... main directory .....");
- info("Reading file " + file);
- parser.parse(file, handler);
+ LDMLParseHandler handler = new LDMLParseHandler(id);
+ parseLDMLFile(file, handler);
bundle = handler.getData();
cldrBundles.put(id, bundle);
- String country = getCountryCode(id);
- if (country != null) {
- bundle = handlerSuppl.getData(country);
+
+ if (id.equals("root")) {
+ // Calendar data (firstDayOfWeek & minDaysInFirstWeek)
+ bundle = handlerSuppl.getData("root");
if (bundle != null) {
//merge two maps into one map
Map temp = cldrBundles.remove(id);
@@ -379,98 +380,44 @@
// SupplementalData file also provides the "parent" locales which
// are othrwise not to be fallen back. Process them here as well.
//
- info("..... Parsing supplementalData.xml .....");
- SAXParserFactory factorySuppl = SAXParserFactory.newInstance();
- factorySuppl.setValidating(true);
- SAXParser parserSuppl = factorySuppl.newSAXParser();
- enableFileAccess(parserSuppl);
handlerSuppl = new SupplementDataParseHandler();
- File fileSupply = new File(SPPL_SOURCE_FILE);
- parserSuppl.parse(fileSupply, handlerSuppl);
+ parseLDMLFile(new File(SPPL_SOURCE_FILE), handlerSuppl);
Map parentData = handlerSuppl.getData("root");
- parentData.keySet().forEach(key -> {
+ parentData.keySet().stream()
+ .filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
+ .forEach(key -> {
parentLocalesMap.put(key, new TreeSet(
Arrays.asList(((String)parentData.get(key)).split(" "))));
});
// Parse numberingSystems to get digit zero character information.
- SAXParserFactory numberingParser = SAXParserFactory.newInstance();
- numberingParser.setValidating(true);
- SAXParser parserNumbering = numberingParser.newSAXParser();
- enableFileAccess(parserNumbering);
handlerNumbering = new NumberingSystemsParseHandler();
- File fileNumbering = new File(NUMBERING_SOURCE_FILE);
- parserNumbering.parse(fileNumbering, handlerNumbering);
+ parseLDMLFile(new File(NUMBERING_SOURCE_FILE), handlerNumbering);
// Parse metaZones to create mappings between Olson tzids and CLDR meta zone names
- info("..... Parsing metaZones.xml .....");
- SAXParserFactory metazonesParser = SAXParserFactory.newInstance();
- metazonesParser.setValidating(true);
- SAXParser parserMetaZones = metazonesParser.newSAXParser();
- enableFileAccess(parserMetaZones);
handlerMetaZones = new MetaZonesParseHandler();
- File fileMetaZones = new File(METAZONES_SOURCE_FILE);
- parserMetaZones.parse(fileMetaZones, handlerMetaZones);
+ parseLDMLFile(new File(METAZONES_SOURCE_FILE), handlerMetaZones);
// Parse likelySubtags
- info("..... Parsing likelySubtags.xml .....");
- SAXParserFactory likelySubtagsParser = SAXParserFactory.newInstance();
- likelySubtagsParser.setValidating(true);
- SAXParser parserLikelySubtags = likelySubtagsParser.newSAXParser();
- enableFileAccess(parserLikelySubtags);
handlerLikelySubtags = new LikelySubtagsParseHandler();
- File fileLikelySubtags = new File(LIKELYSUBTAGS_SOURCE_FILE);
- parserLikelySubtags.parse(fileLikelySubtags, handlerLikelySubtags);
+ parseLDMLFile(new File(LIKELYSUBTAGS_SOURCE_FILE), handlerLikelySubtags);
}
- /**
- * This method will check if a new region dependent Bundle needs to be
- * generated for this Locale id and targetMap. New Bundle will be generated
- * when Locale id has non empty script and country code and targetMap
- * contains region dependent data. This method will also remove region
- * dependent data from this targetMap after candidate locales check. E.g. It
- * will call genRegionDependentBundle() in case of az_Latn_AZ locale and
- * remove region dependent data from this targetMap so that az_Latn_AZ
- * bundle will not be created. For az_Cyrl_AZ, new Bundle will be generated
- * but region dependent data will not be removed from targetMap as its candidate
- * locales are [az_Cyrl_AZ, az_Cyrl, root], which does not include az_AZ for
- * fallback.
- *
- */
+ // Parsers for data in "bcp47" directory
+ //
+ private static void parseBCP47() throws Exception {
+ // Parse timezone
+ handlerTimeZone = new TimeZoneParseHandler();
+ parseLDMLFile(new File(TIMEZONE_SOURCE_FILE), handlerTimeZone);
+ }
- private static void checkRegionDependentBundle(Map targetMap, String id) {
- if ((CLDRConverter.getScript(id) != "")
- && (CLDRConverter.getCountryCode(id) != "")) {
- Map regionDepDataMap = targetMap
- .keySet()
- .stream()
- .filter(calendarDataFields::contains)
- .collect(Collectors.toMap(k -> k, targetMap::get));
- if (!regionDepDataMap.isEmpty()) {
- Locale cldrLoc = new Locale(CLDRConverter.getLanguageCode(id),
- CLDRConverter.getCountryCode(id));
- genRegionDependentBundle(regionDepDataMap, cldrLoc);
- if (checkCandidateLocales(id, cldrLoc)) {
- // Remove matchedKeys from this targetMap only if checkCandidateLocales() returns true.
- regionDepDataMap.keySet().forEach(targetMap::remove);
- }
- }
- }
- }
- /**
- * This method will generate a new Bundle for region dependent data,
- * minimalDaysInFirstWeek and firstDayOfWeek. Newly generated Bundle will be added
- * to addedBundles list.
- */
- private static void genRegionDependentBundle(Map targetMap, Locale cldrLoc) {
- String localeId = cldrLoc.toString();
- StringBuilder sb = getCandLocales(cldrLoc);
- if (sb.indexOf(localeId) == -1) {
- sb.append(localeId);
- }
- Bundle bundle = new Bundle(localeId, sb.toString(), null, null);
- cldrBundles.put(localeId, targetMap);
- addedBundles.add(bundle);
+ private static void parseLDMLFile(File srcfile, AbstractLDMLHandler handler) throws Exception {
+ info("..... Parsing " + srcfile.getName() + " .....");
+ SAXParserFactory pf = SAXParserFactory.newInstance();
+ pf.setValidating(true);
+ SAXParser parser = pf.newSAXParser();
+ enableFileAccess(parser);
+ parser.parse(srcfile, handler);
}
private static StringBuilder getCandLocales(Locale cldrLoc) {
@@ -491,16 +438,6 @@
return candList;
}
- /**
- * This method will return true, if for a given locale, its language and
- * country specific locale will exist in runtime lookup path. E.g. it will
- * return true for bs_Latn_BA.
- */
- private static boolean checkCandidateLocales(String id, Locale cldrLoc) {
- return(getCandidateLocales(Locale.forLanguageTag(id.replaceAll("_", "-")))
- .contains(cldrLoc));
- }
-
private static void convertBundles(List bundles) throws Exception {
// parent locales map. The mappings are put in base metaInfo file
// for now.
@@ -514,8 +451,6 @@
Map targetMap = bundle.getTargetMap();
- // check if new region DependentBundle needs to be generated for this Locale.
- checkRegionDependentBundle(targetMap, bundle.getID());
EnumSet bundleTypes = bundle.getBundleTypes();
if (bundle.isRoot()) {
@@ -528,40 +463,30 @@
if (bundleTypes.contains(Bundle.Type.LOCALENAMES)) {
Map localeNamesMap = extractLocaleNames(targetMap, bundle.getID());
if (!localeNamesMap.isEmpty() || bundle.isRoot()) {
- metaInfo.get("LocaleNames").add(toLanguageTag(bundle.getID()));
- addLikelySubtags(metaInfo, "LocaleNames", bundle.getID());
bundleGenerator.generateBundle("util", "LocaleNames", bundle.getJavaID(), true, localeNamesMap, BundleType.OPEN);
}
}
if (bundleTypes.contains(Bundle.Type.CURRENCYNAMES)) {
Map currencyNamesMap = extractCurrencyNames(targetMap, bundle.getID(), bundle.getCurrencies());
if (!currencyNamesMap.isEmpty() || bundle.isRoot()) {
- metaInfo.get("CurrencyNames").add(toLanguageTag(bundle.getID()));
- addLikelySubtags(metaInfo, "CurrencyNames", bundle.getID());
bundleGenerator.generateBundle("util", "CurrencyNames", bundle.getJavaID(), true, currencyNamesMap, BundleType.OPEN);
}
}
if (bundleTypes.contains(Bundle.Type.TIMEZONENAMES)) {
Map zoneNamesMap = extractZoneNames(targetMap, bundle.getID());
if (!zoneNamesMap.isEmpty() || bundle.isRoot()) {
- metaInfo.get("TimeZoneNames").add(toLanguageTag(bundle.getID()));
- addLikelySubtags(metaInfo, "TimeZoneNames", bundle.getID());
bundleGenerator.generateBundle("util", "TimeZoneNames", bundle.getJavaID(), true, zoneNamesMap, BundleType.TIMEZONE);
}
}
if (bundleTypes.contains(Bundle.Type.CALENDARDATA)) {
Map calendarDataMap = extractCalendarData(targetMap, bundle.getID());
if (!calendarDataMap.isEmpty() || bundle.isRoot()) {
- metaInfo.get("CalendarData").add(toLanguageTag(bundle.getID()));
- addLikelySubtags(metaInfo, "CalendarData", bundle.getID());
bundleGenerator.generateBundle("util", "CalendarData", bundle.getJavaID(), true, calendarDataMap, BundleType.PLAIN);
}
}
if (bundleTypes.contains(Bundle.Type.FORMATDATA)) {
Map formatDataMap = extractFormatData(targetMap, bundle.getID());
if (!formatDataMap.isEmpty() || bundle.isRoot()) {
- metaInfo.get("FormatData").add(toLanguageTag(bundle.getID()));
- addLikelySubtags(metaInfo, "FormatData", bundle.getID());
bundleGenerator.generateBundle("text", "FormatData", bundle.getJavaID(), true, formatDataMap, BundleType.PLAIN);
}
}
@@ -570,43 +495,9 @@
metaInfo.get("AvailableLocales").add(toLanguageTag(bundle.getID()));
addLikelySubtags(metaInfo, "AvailableLocales", bundle.getID());
}
- addCldrImplicitLocales(metaInfo);
bundleGenerator.generateMetaInfo(metaInfo);
}
- /**
- * These are the Locales that are implicitly supported by CLDR.
- * Adding them explicitly as likelySubtags here, will ensure that
- * COMPAT locales do not precede them during ResourceBundle search path.
- */
- private static void addCldrImplicitLocales(Map> metaInfo) {
- metaInfo.get("LocaleNames").add("zh-Hans-CN");
- metaInfo.get("LocaleNames").add("zh-Hans-SG");
- metaInfo.get("LocaleNames").add("zh-Hant-HK");
- metaInfo.get("LocaleNames").add("zh-Hant-MO");
- metaInfo.get("LocaleNames").add("zh-Hant-TW");
- metaInfo.get("CurrencyNames").add("zh-Hans-CN");
- metaInfo.get("CurrencyNames").add("zh-Hans-SG");
- metaInfo.get("CurrencyNames").add("zh-Hant-HK");
- metaInfo.get("CurrencyNames").add("zh-Hant-MO");
- metaInfo.get("CurrencyNames").add("zh-Hant-TW");
- metaInfo.get("TimeZoneNames").add("zh-Hans-CN");
- metaInfo.get("TimeZoneNames").add("zh-Hans-SG");
- metaInfo.get("TimeZoneNames").add("zh-Hant-HK");
- metaInfo.get("TimeZoneNames").add("zh-Hant-MO");
- metaInfo.get("TimeZoneNames").add("zh-Hant-TW");
- metaInfo.get("TimeZoneNames").add("zh-HK");
- metaInfo.get("CalendarData").add("zh-Hans-CN");
- metaInfo.get("CalendarData").add("zh-Hans-SG");
- metaInfo.get("CalendarData").add("zh-Hant-HK");
- metaInfo.get("CalendarData").add("zh-Hant-MO");
- metaInfo.get("CalendarData").add("zh-Hant-TW");
- metaInfo.get("FormatData").add("zh-Hans-CN");
- metaInfo.get("FormatData").add("zh-Hans-SG");
- metaInfo.get("FormatData").add("zh-Hant-HK");
- metaInfo.get("FormatData").add("zh-Hant-MO");
- metaInfo.get("FormatData").add("zh-Hant-TW");
- }
static final Map aliases = new HashMap<>();
/**
@@ -656,14 +547,6 @@
return Locale.forLanguageTag(id.replaceAll("_", "-")).getCountry();
}
- /*
- * Returns the script portion of the given id.
- * If id is "root", "" is returned.
- */
- static String getScript(String id) {
- return "root".equals(id) ? "" : Locale.forLanguageTag(id.replaceAll("_", "-")).getScript();
- }
-
private static class KeyComparator implements Comparator {
static KeyComparator INSTANCE = new KeyComparator();
@@ -695,9 +578,25 @@
Map localeNames = new TreeMap<>(KeyComparator.INSTANCE);
for (String key : map.keySet()) {
if (key.startsWith(LOCALE_NAME_PREFIX)) {
- localeNames.put(key.substring(LOCALE_NAME_PREFIX.length()), map.get(key));
+ switch (key) {
+ case LOCALE_SEPARATOR:
+ localeNames.put("ListCompositionPattern", map.get(key));
+ break;
+ case LOCALE_KEYTYPE:
+ localeNames.put("ListKeyTypePattern", map.get(key));
+ break;
+ default:
+ localeNames.put(key.substring(LOCALE_NAME_PREFIX.length()), map.get(key));
+ break;
+ }
}
}
+
+ if (id.equals("root")) {
+ // Add display name pattern, which is not in CLDR
+ localeNames.put("DisplayNamePattern", "{0,choice,0#|1#{1}|2#{1} ({2})}");
+ }
+
return localeNames;
}
@@ -778,10 +677,30 @@
return names;
}
+ /**
+ * Extracts the language independent calendar data. Each of the two keys,
+ * "firstDayOfWeek" and "minimalDaysInFirstWeek" has a string value consists of
+ * one or multiple occurrences of:
+ * i: rg1 rg2 ... rgn;
+ * where "i" is the data for the following regions (delimited by a space) after
+ * ":", and ends with a ";".
+ */
private static Map extractCalendarData(Map map, String id) {
Map calendarData = new LinkedHashMap<>();
- copyIfPresent(map, "firstDayOfWeek", calendarData);
- copyIfPresent(map, "minimalDaysInFirstWeek", calendarData);
+ if (id.equals("root")) {
+ calendarData.put("firstDayOfWeek",
+ IntStream.range(1, 8)
+ .mapToObj(String::valueOf)
+ .filter(d -> map.keySet().contains(CALENDAR_FIRSTDAY_PREFIX + d))
+ .map(d -> d + ": " + map.get(CALENDAR_FIRSTDAY_PREFIX + d))
+ .collect(Collectors.joining(";")));
+ calendarData.put("minimalDaysInFirstWeek",
+ IntStream.range(0, 7)
+ .mapToObj(String::valueOf)
+ .filter(d -> map.keySet().contains(CALENDAR_MINDAYS_PREFIX + d))
+ .map(d -> d + ": " + map.get(CALENDAR_MINDAYS_PREFIX + d))
+ .collect(Collectors.joining(";")));
+ }
return calendarData;
}
@@ -844,17 +763,19 @@
for (String key : map.keySet()) {
// Copy available calendar names
- if (key.startsWith(CLDRConverter.CALENDAR_NAME_PREFIX)) {
- String type = key.substring(CLDRConverter.CALENDAR_NAME_PREFIX.length());
+ if (key.startsWith(CLDRConverter.LOCALE_TYPE_PREFIX_CA)) {
+ String type = key.substring(CLDRConverter.LOCALE_TYPE_PREFIX_CA.length());
for (CalendarType calendarType : CalendarType.values()) {
if (calendarType == CalendarType.GENERIC) {
continue;
}
if (type.equals(calendarType.lname())) {
Object value = map.get(key);
- formatData.put(key, value);
- String ukey = CLDRConverter.CALENDAR_NAME_PREFIX + calendarType.uname();
- if (!key.equals(ukey)) {
+ String dataKey = key.replace(LOCALE_TYPE_PREFIX_CA,
+ CALENDAR_NAME_PREFIX);
+ formatData.put(dataKey, value);
+ String ukey = CALENDAR_NAME_PREFIX + calendarType.uname();
+ if (!dataKey.equals(ukey)) {
formatData.put(ukey, value);
}
}
@@ -874,6 +795,18 @@
copyIfPresent(map, "NumberElements", formatData);
}
copyIfPresent(map, "NumberPatterns", formatData);
+
+ // put extra number elements for available scripts into formatData, if it is "root"
+ if (id.equals("root")) {
+ handlerNumbering.keySet().stream()
+ .filter(k -> !numberingScripts.contains(k))
+ .forEach(k -> {
+ String[] ne = (String[])map.get("latn.NumberElements");
+ String[] neNew = Arrays.copyOf(ne, ne.length);
+ neNew[4] = handlerNumbering.get(k).substring(0, 1);
+ formatData.put(k + ".NumberElements", neNew);
+ });
+ }
return formatData;
}
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java
--- a/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java Mon Dec 11 16:43:11 2017 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/LDMLParseHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -76,12 +76,16 @@
// ignore this element - it has language and territory elements that aren't locale data
pushIgnoredContainer(qName);
break;
- case "type":
- if ("calendar".equals(attributes.getValue("key"))) {
- pushStringEntry(qName, attributes, CLDRConverter.CALENDAR_NAME_PREFIX + attributes.getValue("type"));
- } else {
- pushIgnoredContainer(qName);
- }
+
+ // for LocaleNames
+ // copy string
+ case "localeSeparator":
+ pushStringEntry(qName, attributes,
+ CLDRConverter.LOCALE_SEPARATOR);
+ break;
+ case "localeKeyTypePattern":
+ pushStringEntry(qName, attributes,
+ CLDRConverter.LOCALE_KEYTYPE);
break;
case "language":
@@ -96,6 +100,24 @@
attributes.getValue("type"));
break;
+ case "key":
+ // for LocaleNames
+ // copy string
+ pushStringEntry(qName, attributes,
+ CLDRConverter.LOCALE_KEY_PREFIX +
+ convertOldKeyName(attributes.getValue("type")));
+ break;
+
+ case "type":
+ // for LocaleNames/CalendarNames
+ // copy string
+ pushStringEntry(qName, attributes,
+ CLDRConverter.LOCALE_TYPE_PREFIX +
+ convertOldKeyName(attributes.getValue("key")) + "." +
+ attributes.getValue("type"));
+
+ break;
+
//
// Currency information
//
@@ -515,26 +537,10 @@
currentNumberingSystem = script + ".";
String digits = CLDRConverter.handlerNumbering.get(script);
if (digits == null) {
- throw new InternalError("null digits for " + script);
- }
- if (Character.isSurrogate(digits.charAt(0))) {
- // DecimalFormatSymbols doesn't support supplementary characters as digit zero.
pushIgnoredContainer(qName);
break;
}
- // in case digits are in the reversed order, reverse back the order.
- if (digits.charAt(0) > digits.charAt(digits.length() - 1)) {
- StringBuilder sb = new StringBuilder(digits);
- digits = sb.reverse().toString();
- }
- // Check if the order is sequential.
- char c0 = digits.charAt(0);
- for (int i = 1; i < digits.length(); i++) {
- if (digits.charAt(i) != c0 + i) {
- pushIgnoredContainer(qName);
- break symbols;
- }
- }
+
@SuppressWarnings("unchecked")
List numberingScripts = (List) get("numberingScripts");
if (numberingScripts == null) {
@@ -924,17 +930,35 @@
}
}
} else if (currentContainer instanceof Entry) {
- Entry> entry = (Entry>) currentContainer;
- Object value = entry.getValue();
- if (value != null) {
- String key = entry.getKey();
- // Tweak for MonthNames for the root locale, Needed for
- // SimpleDateFormat.format()/parse() roundtrip.
- if (id.equals("root") && key.startsWith("MonthNames")) {
- value = new DateFormatSymbols(Locale.US).getShortMonths();
- }
- put(entry.getKey(), value);
+ Entry> entry = (Entry>) currentContainer;
+ Object value = entry.getValue();
+ if (value != null) {
+ String key = entry.getKey();
+ // Tweak for MonthNames for the root locale, Needed for
+ // SimpleDateFormat.format()/parse() roundtrip.
+ if (id.equals("root") && key.startsWith("MonthNames")) {
+ value = new DateFormatSymbols(Locale.US).getShortMonths();
}
+ put(entry.getKey(), value);
}
}
}
+
+ public String convertOldKeyName(String key) {
+ // Explicitly obtained from "alias" attribute in each "key" element.
+ switch (key) {
+ case "calendar":
+ return "ca";
+ case "currency":
+ return "cu";
+ case "collation":
+ return "co";
+ case "numbers":
+ return "nu";
+ case "timezone":
+ return "tz";
+ default:
+ return key;
+ }
+ }
+}
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/NumberingSystemsParseHandler.java
--- a/make/jdk/src/classes/build/tools/cldrconverter/NumberingSystemsParseHandler.java Mon Dec 11 16:43:11 2017 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/NumberingSystemsParseHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -54,9 +54,32 @@
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
switch (qName) {
case "numberingSystem":
- if ("numeric".equals(attributes.getValue("type"))) {
- // eg,
- put(attributes.getValue("id"), attributes.getValue("digits"));
+ numberingSystem: {
+ if ("numeric".equals(attributes.getValue("type"))) {
+ // eg,
+ String script = attributes.getValue("id");
+ String digits = attributes.getValue("digits");
+
+ if (Character.isSurrogate(digits.charAt(0))) {
+ // DecimalFormatSymbols doesn't support supplementary characters as digit zero.
+ break numberingSystem;
+ }
+ // in case digits are in the reversed order, reverse back the order.
+ if (digits.charAt(0) > digits.charAt(digits.length() - 1)) {
+ StringBuilder sb = new StringBuilder(digits);
+ digits = sb.reverse().toString();
+ }
+ // Check if the order is sequential.
+ char c0 = digits.charAt(0);
+ for (int i = 1; i < digits.length(); i++) {
+ if (digits.charAt(i) != c0 + i) {
+ break numberingSystem;
+ }
+ }
+
+ // script/digits are acceptable.
+ put(script, digits);
+ }
}
pushIgnoredContainer(qName);
break;
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
--- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Mon Dec 11 16:43:11 2017 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -256,20 +256,21 @@
CLDRConverter.info("Generating file " + file);
try (PrintWriter out = new PrintWriter(file, "us-ascii")) {
- out.println(CopyrightHeaders.getOpenJDKCopyright());
+ out.printf(CopyrightHeaders.getOpenJDKCopyright());
- out.println((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
+ out.printf((CLDRConverter.isBaseModule ? "package sun.util.cldr;\n\n" :
"package sun.util.resources.cldr.provider;\n\n")
+ "import java.util.HashMap;\n"
+ "import java.util.Locale;\n"
+ "import java.util.Map;\n"
- + "import sun.util.locale.provider.LocaleProviderAdapter;\n"
- + "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
+ + "import sun.util.locale.provider.LocaleDataMetaInfo;\n"
+ + "import sun.util.locale.provider.LocaleProviderAdapter;\n\n");
out.printf("public class %s implements LocaleDataMetaInfo {\n", className);
- out.println(" private static final Map resourceNameToLocales = new HashMap<>();\n" +
- (CLDRConverter.isBaseModule ?
- " private static final Map parentLocalesMap = new HashMap<>();\n\n" : "\n") +
- " static {\n");
+ out.printf(" private static final Map resourceNameToLocales = new HashMap<>();\n" +
+ (CLDRConverter.isBaseModule ?
+ " private static final Map parentLocalesMap = new HashMap<>();\n\n" :
+ "\n") +
+ " static {\n");
for (String key : metaInfo.keySet()) {
if (key.startsWith(CLDRConverter.PARENT_LOCALE_PREFIX)) {
@@ -296,30 +297,50 @@
}
out.printf("\n });\n");
} else {
- out.printf(" resourceNameToLocales.put(\"%s\",\n", key);
- out.printf(" \"%s\");\n",
- toLocaleList(key.equals("FormatData") ? metaInfo.get("AvailableLocales") :
- metaInfo.get(key), false));
+ if ("AvailableLocales".equals(key)) {
+ out.printf(" resourceNameToLocales.put(\"%s\",\n", key);
+ out.printf(" \"%s\");\n", toLocaleList(metaInfo.get(key), false));
+ }
}
}
- out.println(" }\n\n");
+
+ out.printf(" }\n\n");
+
+ // end of static initializer block.
- out.println(" @Override\n" +
+ // Short TZ names for delayed initialization
+ if (CLDRConverter.isBaseModule) {
+ out.printf(" private static class TZShortIDMapHolder {\n");
+ out.printf(" static final Map tzShortIDMap = new HashMap<>();\n");
+ out.printf(" static {\n");
+ CLDRConverter.handlerTimeZone.getData().entrySet().stream()
+ .forEach(e -> {
+ out.printf(" tzShortIDMap.put(\"%s\", \"%s\");\n", e.getKey(),
+ ((String)e.getValue()));
+ });
+ out.printf(" }\n }\n\n");
+ }
+
+ out.printf(" @Override\n" +
" public LocaleProviderAdapter.Type getType() {\n" +
" return LocaleProviderAdapter.Type.CLDR;\n" +
" }\n\n");
- out.println(" @Override\n" +
+ out.printf(" @Override\n" +
" public String availableLanguageTags(String category) {\n" +
" return resourceNameToLocales.getOrDefault(category, \"\");\n" +
" }\n\n");
if (CLDRConverter.isBaseModule) {
+ out.printf(" @Override\n" +
+ " public Map tzShortIDs() {\n" +
+ " return TZShortIDMapHolder.tzShortIDMap;\n" +
+ " }\n\n");
out.printf(" public Map parentLocales() {\n" +
" return parentLocalesMap;\n" +
" }\n}");
} else {
- out.println("}");
+ out.printf("}");
}
}
}
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java
--- a/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java Mon Dec 11 16:43:11 2017 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/SupplementDataParseHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -84,53 +84,18 @@
values.put(CLDRConverter.PARENT_LOCALE_PREFIX+key,
parentLocalesMap.get(key));
});
- } else {
- String countryData = getWeekData(id, JAVA_FIRSTDAY, firstDayMap);
- if (countryData != null) {
- values.put(JAVA_FIRSTDAY, countryData);
- }
- String minDaysData = getWeekData(id, JAVA_MINDAY, minDaysMap);
- if (minDaysData != null) {
- values.put(JAVA_MINDAY, minDaysData);
- }
+ firstDayMap.keySet().forEach(key -> {
+ values.put(CLDRConverter.CALENDAR_FIRSTDAY_PREFIX+firstDayMap.get(key),
+ key);
+ });
+ minDaysMap.keySet().forEach(key -> {
+ values.put(CLDRConverter.CALENDAR_MINDAYS_PREFIX+minDaysMap.get(key),
+ key);
+ });
}
return values.isEmpty() ? null : values;
}
- /**
- * It returns either firstDay or minDays in the JRE format for the country.
- *
- * @param country territory code of the requested data
- * @param jreDataName JAVA_FIRSTDAY or JAVA_MINDAY
- * @param dataMap firstDayMap or minDaysMap
- * @return the value for the given jreDataName, or null if requested value
- * (firstDay/minDays) is not available although that is highly unlikely
- * because of the default value for the world (001).
- */
- String getWeekData(String country, final String jreDataName, final Map dataMap) {
- String countryValue = null;
- String defaultWorldValue = null;
- for (String key : dataMap.keySet()) {
- if (key.contains(country)) {
- if (jreDataName.equals(JAVA_FIRSTDAY)) {
- countryValue = DAY_OF_WEEK_MAP.get((String) dataMap.get(key));
- } else if (jreDataName.equals(JAVA_MINDAY)) {
- countryValue = (String) dataMap.get(key);
- }
- if (countryValue != null) {
- return countryValue;
- }
- } else if (key.contains(WORLD)) {
- if (jreDataName.equals(JAVA_FIRSTDAY)) {
- defaultWorldValue = DAY_OF_WEEK_MAP.get((String) dataMap.get(key));
- } else if (jreDataName.equals(JAVA_MINDAY)) {
- defaultWorldValue = (String) dataMap.get(key);
- }
- }
- }
- return defaultWorldValue;
- }
-
@Override
public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException {
// avoid HTTP traffic to unicode.org
@@ -152,7 +117,33 @@
switch (qName) {
case "firstDay":
if (!isIgnored(attributes)) {
- firstDayMap.put(attributes.getValue("territories"), attributes.getValue("day"));
+ String fd;
+
+ switch (attributes.getValue("day")) {
+ case "sun":
+ fd = "1";
+ break;
+ default:
+ case "mon":
+ fd = "2";
+ break;
+ case "tue":
+ fd = "3";
+ break;
+ case "wed":
+ fd = "4";
+ break;
+ case "thu":
+ fd = "5";
+ break;
+ case "fri":
+ fd = "6";
+ break;
+ case "sat":
+ fd = "7";
+ break;
+ }
+ firstDayMap.put(attributes.getValue("territories"), fd);
}
break;
case "minDays":
diff -r 907bddce488c -r b6ff245c0db6 make/jdk/src/classes/build/tools/cldrconverter/TimeZoneParseHandler.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/src/classes/build/tools/cldrconverter/TimeZoneParseHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 build.tools.cldrconverter;
+
+import java.io.File;
+import java.io.IOException;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * Handles parsing of timezone.xml and produces a map from short timezone IDs to
+ * tz database IDs.
+ */
+
+class TimeZoneParseHandler extends AbstractLDMLHandler
*
*
{@code $BUILD}, matching {@code
- * (0|[1-9][0-9]*)} --- The build number, incremented for each promoted
+ * (0|[1-9][0-9]*)} — The build number, incremented for each promoted
* build. {@code $BUILD} is reset to {@code 1} when any portion of {@code
* $VNUM} is incremented.
*
- *
{@code $OPT}, matching {@code
- * ([-a-zA-Z0-9.]+)} --- Additional build information, if desired. In
- * the case of an {@code internal} build this will often contain the date
- * and time of the build.
+ *
{@code $OPT}, matching {@code ([-a-zA-Z0-9.]+)}
+ * — Additional build information, if desired. In the case of an
+ * {@code internal} build this will often contain the date and time of the
+ * build.
*
*
*
@@ -1138,7 +1069,7 @@
throw new NullPointerException();
// Shortcut to avoid initializing VersionPattern when creating
- // major version constants during startup
+ // feature-version constants during startup
if (isSimpleNumber(s)) {
return new Version(List.of(Integer.parseInt(s)),
Optional.empty(), Optional.empty(), Optional.empty());
@@ -1195,43 +1126,114 @@
}
/**
- * Returns the major version number.
+ * Returns the value of the feature element of
+ * the version number.
*
- * @return The major version number
+ * @return The value of the feature element
+ *
+ * @since 10
*/
- public int major() {
+ public int feature() {
return version.get(0);
}
/**
- * Returns the minor version number or zero if it
- * was not set.
+ * Returns the value of the interim element of
+ * the version number, or zero if it is absent.
*
- * @return The minor version number or zero if it was not set
+ * @return The value of the interim element, or zero
+ *
+ * @since 10
*/
- public int minor() {
+ public int interim() {
return (version.size() > 1 ? version.get(1) : 0);
}
/**
- * Returns the security version number or zero
- * if it was not set.
+ * Returns the value of the update element of the
+ * version number, or zero if it is absent.
*
- * @return The security version number or zero if it was not set
+ * @return The value of the update element, or zero
+ *
+ * @since 10
*/
- public int security() {
+ public int update() {
return (version.size() > 2 ? version.get(2) : 0);
}
/**
- * Returns an unmodifiable {@link java.util.List List} of the
- * integer numerals contained in the version
- * number. The {@code List} always contains at least one
- * element corresponding to the major version
- * number.
+ * Returns the value of the patch element of the
+ * version number, or zero if it is absent.
+ *
+ * @return The value of the patch element, or zero
+ *
+ * @since 10
+ */
+ public int patch() {
+ return (version.size() > 3 ? version.get(3) : 0);
+ }
+
+ /**
+ * Returns the value of the major element of the version number.
+ *
+ * @deprecated As of Java SE 10, the first element of a version
+ * number is not the major-release number but the feature-release
+ * counter, incremented for every time-based release. Use the {@link
+ * #feature()} method in preference to this method. For compatibility,
+ * this method returns the value of the feature
+ * element.
+ *
+ * @return The value of the feature element
+ */
+ @Deprecated(since = "10")
+ public int major() {
+ return feature();
+ }
+
+ /**
+ * Returns the value of the minor element of the version number, or
+ * zero if it is absent.
*
- * @return An unmodifiable list of the integer numerals
- * contained in the version number
+ * @deprecated As of Java SE 10, the second element of a version
+ * number is not the minor-release number but the interim-release
+ * counter, incremented for every interim release. Use the {@link
+ * #interim()} method in preference to this method. For compatibility,
+ * this method returns the value of the interim
+ * element, or zero if it is absent.
+ *
+ * @return The value of the interim element, or zero
+ */
+ @Deprecated(since = "10")
+ public int minor() {
+ return interim();
+ }
+
+ /**
+ * Returns the value of the security element of the version number, or
+ * zero if it is absent.
+ *
+ * @deprecated As of Java SE 10, the third element of a version
+ * number is not the security level but the update-release counter,
+ * incremented for every update release. Use the {@link #update()}
+ * method in preference to this method. For compatibility, this method
+ * returns the value of the update element, or
+ * zero if it is absent.
+ *
+ * @return The value of the update element, or zero
+ */
+ @Deprecated(since = "10")
+ public int security() {
+ return update();
+ }
+
+ /**
+ * Returns an unmodifiable {@link java.util.List List} of the integers
+ * represented in the version number. The {@code
+ * List} always contains at least one element corresponding to the feature version number.
+ *
+ * @return An unmodifiable list of the integers
+ * represented in the version number
*/
public List version() {
return version;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/String.java
--- a/src/java.base/share/classes/java/lang/String.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/String.java Thu Dec 14 12:28:32 2017 +0000
@@ -3046,6 +3046,10 @@
return COMPACT_STRINGS ? coder : UTF16;
}
+ byte[] value() {
+ return value;
+ }
+
private boolean isLatin1() {
return COMPACT_STRINGS && coder == LATIN1;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/StringCoding.java
--- a/src/java.base/share/classes/java/lang/StringCoding.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/StringCoding.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,11 @@
import static java.lang.String.LATIN1;
import static java.lang.String.UTF16;
import static java.lang.String.COMPACT_STRINGS;
+import static java.lang.Character.isSurrogate;
+import static java.lang.Character.highSurrogate;
+import static java.lang.Character.lowSurrogate;
+import static java.lang.Character.isSupplementaryCodePoint;
+import static java.lang.StringUTF16.putChar;
/**
* Utility class for string encoding and decoding.
@@ -66,8 +71,6 @@
private static final Charset US_ASCII = sun.nio.cs.US_ASCII.INSTANCE;
private static final Charset UTF_8 = sun.nio.cs.UTF_8.INSTANCE;
- private static boolean warnUnsupportedCharset = true;
-
private static T deref(ThreadLocal> tl) {
SoftReference sr = tl.get();
if (sr == null)
@@ -80,7 +83,6 @@
}
// Trim the given byte array to the given length
- //
private static byte[] safeTrim(byte[] ba, int len, boolean isTrusted) {
if (len == ba.length && (isTrusted || System.getSecurityManager() == null))
return ba;
@@ -105,17 +107,6 @@
return null;
}
- private static void warnUnsupportedCharset(String csn) {
- if (warnUnsupportedCharset) {
- // Use err(String) rather than the Logging API or System.err
- // since this method may be called during VM initialization
- // before either is available.
- err("WARNING: Default charset " + csn +
- " not supported, using ISO-8859-1 instead\n");
- warnUnsupportedCharset = false;
- }
- }
-
static class Result {
byte[] value;
byte coder;
@@ -224,19 +215,6 @@
}
}
- private static class StringDecoder8859_1 extends StringDecoder {
- StringDecoder8859_1(Charset cs, String rcn) {
- super(cs, rcn);
- }
- Result decode(byte[] ba, int off, int len) {
- if (COMPACT_STRINGS) {
- return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
- } else {
- return result.with(StringLatin1.inflate(ba, off, len), UTF16);
- }
- }
- }
-
static Result decode(String charsetName, byte[] ba, int off, int len)
throws UnsupportedEncodingException
{
@@ -249,12 +227,15 @@
Charset cs = lookupCharset(csn);
if (cs != null) {
if (cs == UTF_8) {
- sd = new StringDecoderUTF8(cs, csn);
- } else if (cs == ISO_8859_1) {
- sd = new StringDecoder8859_1(cs, csn);
- } else {
- sd = new StringDecoder(cs, csn);
+ return decodeUTF8(ba, off, len, true);
+ }
+ if (cs == ISO_8859_1) {
+ return decodeLatin1(ba, off, len);
}
+ if (cs == US_ASCII) {
+ return decodeASCII(ba, off, len);
+ }
+ sd = new StringDecoder(cs, csn);
}
} catch (IllegalCharsetNameException x) {}
if (sd == null)
@@ -265,6 +246,16 @@
}
static Result decode(Charset cs, byte[] ba, int off, int len) {
+ if (cs == UTF_8) {
+ return decodeUTF8(ba, off, len, true);
+ }
+ if (cs == ISO_8859_1) {
+ return decodeLatin1(ba, off, len);
+ }
+ if (cs == US_ASCII) {
+ return decodeASCII(ba, off, len);
+ }
+
// (1)We never cache the "external" cs, the only benefit of creating
// an additional StringDe/Encoder object to wrap it is to share the
// de/encode() method. These SD/E objects are short-lived, the young-gen
@@ -280,39 +271,29 @@
// check (... && (isTrusted || SM == null || getClassLoader0())) in trim
// but it then can be argued that the SM is null when the operation
// is started...
- if (cs == UTF_8) {
- return StringDecoderUTF8.decode(ba, off, len, new Result());
- }
CharsetDecoder cd = cs.newDecoder();
// ascii fastpath
- if (cs == ISO_8859_1 || ((cd instanceof ArrayDecoder) &&
- ((ArrayDecoder)cd).isASCIICompatible() &&
- !hasNegatives(ba, off, len))) {
- if (COMPACT_STRINGS) {
- return new Result().with(Arrays.copyOfRange(ba, off, off + len),
- LATIN1);
- } else {
- return new Result().with(StringLatin1.inflate(ba, off, len), UTF16);
- }
+ if ((cd instanceof ArrayDecoder) &&
+ ((ArrayDecoder)cd).isASCIICompatible() && !hasNegatives(ba, off, len)) {
+ return decodeLatin1(ba, off, len);
}
int en = scale(len, cd.maxCharsPerByte());
if (len == 0) {
return new Result().with();
}
- if (cs.getClass().getClassLoader0() != null &&
- System.getSecurityManager() != null) {
- ba = Arrays.copyOfRange(ba, off, off + len);
- off = 0;
- }
cd.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.reset();
-
char[] ca = new char[en];
if (cd instanceof ArrayDecoder) {
int clen = ((ArrayDecoder)cd).decode(ba, off, len, ca);
return new Result().with(ca, 0, clen);
}
+ if (cs.getClass().getClassLoader0() != null &&
+ System.getSecurityManager() != null) {
+ ba = Arrays.copyOfRange(ba, off, off + len);
+ off = 0;
+ }
ByteBuffer bb = ByteBuffer.wrap(ba, off, len);
CharBuffer cb = CharBuffer.wrap(ca);
try {
@@ -331,24 +312,22 @@
}
static Result decode(byte[] ba, int off, int len) {
- String csn = Charset.defaultCharset().name();
- try {
- // use charset name decode() variant which provides caching.
- return decode(csn, ba, off, len);
- } catch (UnsupportedEncodingException x) {
- warnUnsupportedCharset(csn);
+ Charset cs = Charset.defaultCharset();
+ if (cs == UTF_8) {
+ return decodeUTF8(ba, off, len, true);
+ }
+ if (cs == ISO_8859_1) {
+ return decodeLatin1(ba, off, len);
}
- try {
- return decode("ISO-8859-1", ba, off, len);
- } catch (UnsupportedEncodingException x) {
- // If this code is hit during VM initialization, err(String) is
- // the only way we will be able to get any kind of error message.
- err("ISO-8859-1 charset not available: " + x.toString() + "\n");
- // If we can not find ISO-8859-1 (a required encoding) then things
- // are seriously wrong with the installation.
- System.exit(1);
- return null;
+ if (cs == US_ASCII) {
+ return decodeASCII(ba, off, len);
}
+ StringDecoder sd = deref(decoder);
+ if (sd == null || !cs.name().equals(sd.cs.name())) {
+ sd = new StringDecoder(cs, cs.name());
+ set(decoder, sd);
+ }
+ return sd.decode(ba, off, len);
}
// -- Encoding --
@@ -393,9 +372,6 @@
return ba;
}
if (ce instanceof ArrayEncoder) {
- if (!isTrusted) {
- val = Arrays.copyOf(val, val.length);
- }
int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
: ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
if (blen != -1) {
@@ -423,49 +399,140 @@
}
}
- @HotSpotIntrinsicCandidate
- private static int implEncodeISOArray(byte[] sa, int sp,
- byte[] da, int dp, int len) {
- int i = 0;
- for (; i < len; i++) {
- char c = StringUTF16.getChar(sa, sp++);
- if (c > '\u00FF')
- break;
- da[dp++] = (byte)c;
+ static byte[] encode(String charsetName, byte coder, byte[] val)
+ throws UnsupportedEncodingException
+ {
+ StringEncoder se = deref(encoder);
+ String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
+ if ((se == null) || !(csn.equals(se.requestedCharsetName())
+ || csn.equals(se.charsetName()))) {
+ se = null;
+ try {
+ Charset cs = lookupCharset(csn);
+ if (cs != null) {
+ if (cs == UTF_8) {
+ return encodeUTF8(coder, val, true);
+ }
+ if (cs == ISO_8859_1) {
+ return encode8859_1(coder, val);
+ }
+ if (cs == US_ASCII) {
+ return encodeASCII(coder, val);
+ }
+ se = new StringEncoder(cs, csn);
+ }
+ } catch (IllegalCharsetNameException x) {}
+ if (se == null) {
+ throw new UnsupportedEncodingException (csn);
+ }
+ set(encoder, se);
}
- return i;
+ return se.encode(coder, val);
}
- static byte[] encode8859_1(byte coder, byte[] val) {
- if (coder == LATIN1) {
+ static byte[] encode(Charset cs, byte coder, byte[] val) {
+ if (cs == UTF_8) {
+ return encodeUTF8(coder, val, true);
+ }
+ if (cs == ISO_8859_1) {
+ return encode8859_1(coder, val);
+ }
+ if (cs == US_ASCII) {
+ return encodeASCII(coder, val);
+ }
+ CharsetEncoder ce = cs.newEncoder();
+ // fastpath for ascii compatible
+ if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
+ ((ArrayEncoder)ce).isASCIICompatible() &&
+ !hasNegatives(val, 0, val.length)))) {
return Arrays.copyOf(val, val.length);
}
- int len = val.length >> 1;
- byte[] dst = new byte[len];
- int dp = 0;
- int sp = 0;
- int sl = len;
- while (sp < sl) {
- int ret = implEncodeISOArray(val, sp, dst, dp, len);
- sp = sp + ret;
- dp = dp + ret;
- if (ret != len) {
- char c = StringUTF16.getChar(val, sp++);
- if (Character.isHighSurrogate(c) && sp < sl &&
- Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
- sp++;
- }
- dst[dp++] = '?';
- len = sl - sp;
+ int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
+ int en = scale(len, ce.maxBytesPerChar());
+ byte[] ba = new byte[en];
+ if (len == 0) {
+ return ba;
+ }
+ ce.onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE)
+ .reset();
+ if (ce instanceof ArrayEncoder) {
+ int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
+ : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
+ if (blen != -1) {
+ return safeTrim(ba, blen, true);
}
}
- if (dp == dst.length) {
- return dst;
+ boolean isTrusted = cs.getClass().getClassLoader0() == null ||
+ System.getSecurityManager() == null;
+ char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
+ : StringUTF16.toChars(val);
+ ByteBuffer bb = ByteBuffer.wrap(ba);
+ CharBuffer cb = CharBuffer.wrap(ca, 0, len);
+ try {
+ CoderResult cr = ce.encode(cb, bb, true);
+ if (!cr.isUnderflow())
+ cr.throwException();
+ cr = ce.flush(bb);
+ if (!cr.isUnderflow())
+ cr.throwException();
+ } catch (CharacterCodingException x) {
+ throw new Error(x);
}
- return Arrays.copyOf(dst, dp);
+ return safeTrim(ba, bb.position(), isTrusted);
}
- static byte[] encodeASCII(byte coder, byte[] val) {
+ static byte[] encode(byte coder, byte[] val) {
+ Charset cs = Charset.defaultCharset();
+ if (cs == UTF_8) {
+ return encodeUTF8(coder, val, true);
+ }
+ if (cs == ISO_8859_1) {
+ return encode8859_1(coder, val);
+ }
+ if (cs == US_ASCII) {
+ return encodeASCII(coder, val);
+ }
+ StringEncoder se = deref(encoder);
+ if (se == null || !cs.name().equals(se.cs.name())) {
+ se = new StringEncoder(cs, cs.name());
+ set(encoder, se);
+ }
+ return se.encode(coder, val);
+ }
+
+ /**
+ * Print a message directly to stderr, bypassing all character conversion
+ * methods.
+ * @param msg message to print
+ */
+ private static native void err(String msg);
+
+ /* The cached Result for each thread */
+ private static final ThreadLocal
+ resultCached = new ThreadLocal<>() {
+ protected StringCoding.Result initialValue() {
+ return new StringCoding.Result();
+ }};
+
+ ////////////////////////// ascii //////////////////////////////
+
+ private static Result decodeASCII(byte[] ba, int off, int len) {
+ Result result = resultCached.get();
+ if (COMPACT_STRINGS && !hasNegatives(ba, off, len)) {
+ return result.with(Arrays.copyOfRange(ba, off, off + len),
+ LATIN1);
+ }
+ byte[] dst = new byte[len<<1];
+ int dp = 0;
+ while (dp < len) {
+ int b = ba[off++];
+ putChar(dst, dp++, (b >= 0) ? (char)b : repl);
+ }
+ return result.with(dst, UTF16);
+ }
+
+ private static byte[] encodeASCII(byte coder, byte[] val) {
if (coder == LATIN1) {
byte[] dst = new byte[val.length];
for (int i = 0; i < val.length; i++) {
@@ -498,59 +565,51 @@
return Arrays.copyOf(dst, dp);
}
- static byte[] encodeUTF8(byte coder, byte[] val) {
- int dp = 0;
- byte[] dst;
+ ////////////////////////// latin1/8859_1 ///////////////////////////
+
+ private static Result decodeLatin1(byte[] ba, int off, int len) {
+ Result result = resultCached.get();
+ if (COMPACT_STRINGS) {
+ return result.with(Arrays.copyOfRange(ba, off, off + len), LATIN1);
+ } else {
+ return result.with(StringLatin1.inflate(ba, off, len), UTF16);
+ }
+ }
+
+ @HotSpotIntrinsicCandidate
+ private static int implEncodeISOArray(byte[] sa, int sp,
+ byte[] da, int dp, int len) {
+ int i = 0;
+ for (; i < len; i++) {
+ char c = StringUTF16.getChar(sa, sp++);
+ if (c > '\u00FF')
+ break;
+ da[dp++] = (byte)c;
+ }
+ return i;
+ }
+
+ private static byte[] encode8859_1(byte coder, byte[] val) {
if (coder == LATIN1) {
- dst = new byte[val.length << 1];
- for (int sp = 0; sp < val.length; sp++) {
- byte c = val[sp];
- if (c < 0) {
- dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
- dst[dp++] = (byte)(0x80 | (c & 0x3f));
- } else {
- dst[dp++] = c;
+ return Arrays.copyOf(val, val.length);
+ }
+ int len = val.length >> 1;
+ byte[] dst = new byte[len];
+ int dp = 0;
+ int sp = 0;
+ int sl = len;
+ while (sp < sl) {
+ int ret = implEncodeISOArray(val, sp, dst, dp, len);
+ sp = sp + ret;
+ dp = dp + ret;
+ if (ret != len) {
+ char c = StringUTF16.getChar(val, sp++);
+ if (Character.isHighSurrogate(c) && sp < sl &&
+ Character.isLowSurrogate(StringUTF16.getChar(val, sp))) {
+ sp++;
}
- }
- } else {
- int sp = 0;
- int sl = val.length >> 1;
- dst = new byte[sl * 3];
- char c;
- while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
- // ascii fast loop;
- dst[dp++] = (byte)c;
- sp++;
- }
- while (sp < sl) {
- c = StringUTF16.getChar(val, sp++);
- if (c < 0x80) {
- dst[dp++] = (byte)c;
- } else if (c < 0x800) {
- dst[dp++] = (byte)(0xc0 | (c >> 6));
- dst[dp++] = (byte)(0x80 | (c & 0x3f));
- } else if (Character.isSurrogate(c)) {
- int uc = -1;
- char c2;
- if (Character.isHighSurrogate(c) && sp < sl &&
- Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
- uc = Character.toCodePoint(c, c2);
- }
- if (uc < 0) {
- dst[dp++] = '?';
- } else {
- dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
- dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
- dst[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
- dst[dp++] = (byte)(0x80 | (uc & 0x3f));
- sp++; // 2 chars
- }
- } else {
- // 3 bytes, 16 bits
- dst[dp++] = (byte)(0xe0 | ((c >> 12)));
- dst[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
- dst[dp++] = (byte)(0x80 | (c & 0x3f));
- }
+ dst[dp++] = '?';
+ len = sl - sp;
}
}
if (dp == dst.length) {
@@ -559,113 +618,333 @@
return Arrays.copyOf(dst, dp);
}
- static byte[] encode(String charsetName, byte coder, byte[] val)
- throws UnsupportedEncodingException
- {
- StringEncoder se = deref(encoder);
- String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
- if ((se == null) || !(csn.equals(se.requestedCharsetName())
- || csn.equals(se.charsetName()))) {
- se = null;
- try {
- Charset cs = lookupCharset(csn);
- if (cs != null) {
- if (cs == UTF_8) {
- return encodeUTF8(coder, val);
- } else if (cs == ISO_8859_1) {
- return encode8859_1(coder, val);
- } else if (cs == US_ASCII) {
- return encodeASCII(coder, val);
- }
- se = new StringEncoder(cs, csn);
- }
- } catch (IllegalCharsetNameException x) {}
- if (se == null) {
- throw new UnsupportedEncodingException (csn);
- }
- set(encoder, se);
+ //////////////////////////////// utf8 ////////////////////////////////////
+
+ private static boolean isNotContinuation(int b) {
+ return (b & 0xc0) != 0x80;
+ }
+
+ private static boolean isMalformed3(int b1, int b2, int b3) {
+ return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+ (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
+ }
+
+ private static boolean isMalformed3_2(int b1, int b2) {
+ return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+ (b2 & 0xc0) != 0x80;
+ }
+
+ private static boolean isMalformed4(int b2, int b3, int b4) {
+ return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
+ (b4 & 0xc0) != 0x80;
+ }
+
+ private static boolean isMalformed4_2(int b1, int b2) {
+ return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
+ (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+ (b2 & 0xc0) != 0x80;
+ }
+
+ private static boolean isMalformed4_3(int b3) {
+ return (b3 & 0xc0) != 0x80;
+ }
+
+ // for nb == 3/4
+ private static int malformedN(byte[] src, int sp, int nb) {
+ if (nb == 3) {
+ int b1 = src[sp++];
+ int b2 = src[sp++]; // no need to lookup b3
+ return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
+ isNotContinuation(b2)) ? 1 : 2;
+ } else if (nb == 4) { // we don't care the speed here
+ int b1 = src[sp++] & 0xff;
+ int b2 = src[sp++] & 0xff;
+ if (b1 > 0xf4 ||
+ (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
+ (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
+ isNotContinuation(b2))
+ return 1;
+ if (isNotContinuation(src[sp++]))
+ return 2;
+ return 3;
}
- return se.encode(coder, val);
+ assert false;
+ return -1;
+ }
+
+ private static void throwMalformed(int off, int nb) {
+ throw new IllegalArgumentException("malformed input off : " + off +
+ ", length : " + nb);
+ }
+
+ private static char repl = '\ufffd';
+
+ private static Result decodeUTF8(byte[] src, int sp, int len, boolean doReplace) {
+ // ascii-bais, which has a relative impact to the non-ascii-only bytes
+ if (COMPACT_STRINGS && !hasNegatives(src, sp, len))
+ return resultCached.get().with(Arrays.copyOfRange(src, sp, sp + len),
+ LATIN1);
+ return decodeUTF8_0(src, sp, len, doReplace);
}
- static byte[] encode(Charset cs, byte coder, byte[] val) {
- if (cs == UTF_8) {
- return encodeUTF8(coder, val);
- } else if (cs == ISO_8859_1) {
- return encode8859_1(coder, val);
- } else if (cs == US_ASCII) {
- return encodeASCII(coder, val);
- }
- CharsetEncoder ce = cs.newEncoder();
- // fastpath for ascii compatible
- if (coder == LATIN1 && (((ce instanceof ArrayEncoder) &&
- ((ArrayEncoder)ce).isASCIICompatible() &&
- !hasNegatives(val, 0, val.length)))) {
- return Arrays.copyOf(val, val.length);
- }
- int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
- int en = scale(len, ce.maxBytesPerChar());
- byte[] ba = new byte[en];
- if (len == 0) {
- return ba;
- }
- boolean isTrusted = cs.getClass().getClassLoader0() == null ||
- System.getSecurityManager() == null;
- ce.onMalformedInput(CodingErrorAction.REPLACE)
- .onUnmappableCharacter(CodingErrorAction.REPLACE)
- .reset();
- if (ce instanceof ArrayEncoder) {
- if (!isTrusted) {
- val = Arrays.copyOf(val, val.length);
+ private static Result decodeUTF8_0(byte[] src, int sp, int len, boolean doReplace) {
+ Result ret = resultCached.get();
+
+ int sl = sp + len;
+ int dp = 0;
+ byte[] dst = new byte[len];
+
+ if (COMPACT_STRINGS) {
+ while (sp < sl) {
+ int b1 = src[sp];
+ if (b1 >= 0) {
+ dst[dp++] = (byte)b1;
+ sp++;
+ continue;
+ }
+ if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
+ sp + 1 < sl) {
+ int b2 = src[sp + 1];
+ if (!isNotContinuation(b2)) {
+ dst[dp++] = (byte)(((b1 << 6) ^ b2)^
+ (((byte) 0xC0 << 6) ^
+ ((byte) 0x80 << 0)));
+ sp += 2;
+ continue;
+ }
+ }
+ // anything not a latin1, including the repl
+ // we have to go with the utf16
+ break;
}
- int blen = (coder == LATIN1 ) ? ((ArrayEncoder)ce).encodeFromLatin1(val, 0, len, ba)
- : ((ArrayEncoder)ce).encodeFromUTF16(val, 0, len, ba);
- if (blen != -1) {
- return safeTrim(ba, blen, isTrusted);
+ if (sp == sl) {
+ if (dp != dst.length) {
+ dst = Arrays.copyOf(dst, dp);
+ }
+ return ret.with(dst, LATIN1);
}
}
- char[] ca = (coder == LATIN1 ) ? StringLatin1.toChars(val)
- : StringUTF16.toChars(val);
- ByteBuffer bb = ByteBuffer.wrap(ba);
- CharBuffer cb = CharBuffer.wrap(ca, 0, len);
- try {
- CoderResult cr = ce.encode(cb, bb, true);
- if (!cr.isUnderflow())
- cr.throwException();
- cr = ce.flush(bb);
- if (!cr.isUnderflow())
- cr.throwException();
- } catch (CharacterCodingException x) {
- throw new Error(x);
+ if (dp == 0) {
+ dst = new byte[len << 1];
+ } else {
+ byte[] buf = new byte[len << 1];
+ StringLatin1.inflate(dst, 0, buf, 0, dp);
+ dst = buf;
}
- return safeTrim(ba, bb.position(), isTrusted);
+ while (sp < sl) {
+ int b1 = src[sp++];
+ if (b1 >= 0) {
+ putChar(dst, dp++, (char) b1);
+ } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
+ if (sp < sl) {
+ int b2 = src[sp++];
+ if (isNotContinuation(b2)) {
+ if (!doReplace) {
+ throwMalformed(sp - 1, 1);
+ }
+ putChar(dst, dp++, repl);
+ sp--;
+ } else {
+ putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
+ (((byte) 0xC0 << 6) ^
+ ((byte) 0x80 << 0))));
+ }
+ continue;
+ }
+ if (!doReplace) {
+ throwMalformed(sp, 1); // underflow()
+ }
+ putChar(dst, dp++, repl);
+ break;
+ } else if ((b1 >> 4) == -2) {
+ if (sp + 1 < sl) {
+ int b2 = src[sp++];
+ int b3 = src[sp++];
+ if (isMalformed3(b1, b2, b3)) {
+ if (!doReplace) {
+ throwMalformed(sp - 3, 3);
+ }
+ putChar(dst, dp++, repl);
+ sp -= 3;
+ sp += malformedN(src, sp, 3);
+ } else {
+ char c = (char)((b1 << 12) ^
+ (b2 << 6) ^
+ (b3 ^
+ (((byte) 0xE0 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0))));
+ if (isSurrogate(c)) {
+ if (!doReplace) {
+ throwMalformed(sp - 3, 3);
+ }
+ putChar(dst, dp++, repl);
+ } else {
+ putChar(dst, dp++, c);
+ }
+ }
+ continue;
+ }
+ if (sp < sl && isMalformed3_2(b1, src[sp])) {
+ if (!doReplace) {
+ throwMalformed(sp - 1, 2);
+ }
+ putChar(dst, dp++, repl);
+ continue;
+ }
+ if (!doReplace){
+ throwMalformed(sp, 1);
+ }
+ putChar(dst, dp++, repl);
+ break;
+ } else if ((b1 >> 3) == -2) {
+ if (sp + 2 < sl) {
+ int b2 = src[sp++];
+ int b3 = src[sp++];
+ int b4 = src[sp++];
+ int uc = ((b1 << 18) ^
+ (b2 << 12) ^
+ (b3 << 6) ^
+ (b4 ^
+ (((byte) 0xF0 << 18) ^
+ ((byte) 0x80 << 12) ^
+ ((byte) 0x80 << 6) ^
+ ((byte) 0x80 << 0))));
+ if (isMalformed4(b2, b3, b4) ||
+ !isSupplementaryCodePoint(uc)) { // shortest form check
+ if (!doReplace) {
+ throwMalformed(sp - 4, 4);
+ }
+ putChar(dst, dp++, repl);
+ sp -= 4;
+ sp += malformedN(src, sp, 4);
+ } else {
+ putChar(dst, dp++, highSurrogate(uc));
+ putChar(dst, dp++, lowSurrogate(uc));
+ }
+ continue;
+ }
+ b1 &= 0xff;
+ if (b1 > 0xf4 ||
+ sp < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
+ if (!doReplace) {
+ throwMalformed(sp - 1, 1); // or 2
+ }
+ putChar(dst, dp++, repl);
+ continue;
+ }
+ if (!doReplace) {
+ throwMalformed(sp - 1, 1);
+ }
+ sp++;
+ putChar(dst, dp++, repl);
+ if (sp < sl && isMalformed4_3(src[sp])) {
+ continue;
+ }
+ break;
+ } else {
+ if (!doReplace) {
+ throwMalformed(sp - 1, 1);
+ }
+ putChar(dst, dp++, repl);
+ }
+ }
+ if (dp != len) {
+ dst = Arrays.copyOf(dst, dp << 1);
+ }
+ return ret.with(dst, UTF16);
}
- static byte[] encode(byte coder, byte[] val) {
- String csn = Charset.defaultCharset().name();
- try {
- // use charset name encode() variant which provides caching.
- return encode(csn, coder, val);
- } catch (UnsupportedEncodingException x) {
- warnUnsupportedCharset(csn);
+ private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) {
+ if (coder == UTF16)
+ return encodeUTF8_UTF16(val, doReplace);
+
+ if (!hasNegatives(val, 0, val.length))
+ return Arrays.copyOf(val, val.length);
+
+ int dp = 0;
+ byte[] dst = new byte[val.length << 1];
+ for (int sp = 0; sp < val.length; sp++) {
+ byte c = val[sp];
+ if (c < 0) {
+ dst[dp++] = (byte)(0xc0 | ((c & 0xff) >> 6));
+ dst[dp++] = (byte)(0x80 | (c & 0x3f));
+ } else {
+ dst[dp++] = c;
+ }
}
- try {
- return encode("ISO-8859-1", coder, val);
- } catch (UnsupportedEncodingException x) {
- // If this code is hit during VM initialization, err(String) is
- // the only way we will be able to get any kind of error message.
- err("ISO-8859-1 charset not available: " + x.toString() + "\n");
- // If we can not find ISO-8859-1 (a required encoding) then things
- // are seriously wrong with the installation.
- System.exit(1);
- return null;
- }
+ if (dp == dst.length)
+ return dst;
+ return Arrays.copyOf(dst, dp);
}
- /**
- * Print a message directly to stderr, bypassing all character conversion
- * methods.
- * @param msg message to print
+ private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) {
+ int dp = 0;
+ int sp = 0;
+ int sl = val.length >> 1;
+ byte[] dst = new byte[sl * 3];
+ char c;
+ while (sp < sl && (c = StringUTF16.getChar(val, sp)) < '\u0080') {
+ // ascii fast loop;
+ dst[dp++] = (byte)c;
+ sp++;
+ }
+ while (sp < sl) {
+ c = StringUTF16.getChar(val, sp++);
+ if (c < 0x80) {
+ dst[dp++] = (byte)c;
+ } else if (c < 0x800) {
+ dst[dp++] = (byte)(0xc0 | (c >> 6));
+ dst[dp++] = (byte)(0x80 | (c & 0x3f));
+ } else if (Character.isSurrogate(c)) {
+ int uc = -1;
+ char c2;
+ if (Character.isHighSurrogate(c) && sp < sl &&
+ Character.isLowSurrogate(c2 = StringUTF16.getChar(val, sp))) {
+ uc = Character.toCodePoint(c, c2);
+ }
+ if (uc < 0) {
+ if (doReplace) {
+ dst[dp++] = '?';
+ } else {
+ throwMalformed(sp - 1, 1); // or 2, does not matter here
+ }
+ } else {
+ dst[dp++] = (byte)(0xf0 | ((uc >> 18)));
+ dst[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
+ dst[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
+ dst[dp++] = (byte)(0x80 | (uc & 0x3f));
+ sp++; // 2 chars
+ }
+ } else {
+ // 3 bytes, 16 bits
+ dst[dp++] = (byte)(0xe0 | ((c >> 12)));
+ dst[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
+ dst[dp++] = (byte)(0x80 | (c & 0x3f));
+ }
+ }
+ if (dp == dst.length) {
+ return dst;
+ }
+ return Arrays.copyOf(dst, dp);
+ }
+
+ ////////////////////// for j.u.z.ZipCoder //////////////////////////
+
+ /*
+ * Throws iae, instead of replacing, if malformed or unmappble.
*/
- private static native void err(String msg);
+ static String newStringUTF8NoRepl(byte[] src, int off, int len) {
+ if (COMPACT_STRINGS && !hasNegatives(src, off, len))
+ return new String(Arrays.copyOfRange(src, off, off + len), LATIN1);
+ Result ret = decodeUTF8_0(src, off, len, false);
+ return new String(ret.value, ret.coder);
+ }
+
+ /*
+ * Throws iae, instead of replacing, if unmappble.
+ */
+ static byte[] getBytesUTF8NoRepl(String s) {
+ return encodeUTF8(s.coder(), s.value(), false);
+ }
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/StringDecoderUTF8.java
--- a/src/java.base/share/classes/java/lang/StringDecoderUTF8.java Mon Dec 11 16:43:11 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +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. 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;
-
-import java.nio.charset.Charset;
-import java.util.Arrays;
-
-import static java.lang.String.LATIN1;
-import static java.lang.String.UTF16;
-import static java.lang.String.COMPACT_STRINGS;
-import static java.lang.Character.isSurrogate;
-import static java.lang.Character.highSurrogate;
-import static java.lang.Character.lowSurrogate;
-import static java.lang.Character.isSupplementaryCodePoint;
-import static java.lang.StringUTF16.putChar;
-
-class StringDecoderUTF8 extends StringCoding.StringDecoder {
-
- StringDecoderUTF8(Charset cs, String rcn) {
- super(cs, rcn);
- }
-
- private static boolean isNotContinuation(int b) {
- return (b & 0xc0) != 0x80;
- }
-
- private static boolean isMalformed3(int b1, int b2, int b3) {
- return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
- (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80;
- }
-
- private static boolean isMalformed3_2(int b1, int b2) {
- return (b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
- (b2 & 0xc0) != 0x80;
- }
-
- private static boolean isMalformed4(int b2, int b3, int b4) {
- return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
- (b4 & 0xc0) != 0x80;
- }
-
- private static boolean isMalformed4_2(int b1, int b2) {
- return (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
- (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
- (b2 & 0xc0) != 0x80;
- }
-
- private static boolean isMalformed4_3(int b3) {
- return (b3 & 0xc0) != 0x80;
- }
-
- // for nb == 3/4
- private static int malformedN(byte[] src, int sp, int nb) {
- if (nb == 3) {
- int b1 = src[sp++];
- int b2 = src[sp++]; // no need to lookup b3
- return ((b1 == (byte)0xe0 && (b2 & 0xe0) == 0x80) ||
- isNotContinuation(b2)) ? 1 : 2;
- } else if (nb == 4) { // we don't care the speed here
- int b1 = src[sp++] & 0xff;
- int b2 = src[sp++] & 0xff;
- if (b1 > 0xf4 ||
- (b1 == 0xf0 && (b2 < 0x90 || b2 > 0xbf)) ||
- (b1 == 0xf4 && (b2 & 0xf0) != 0x80) ||
- isNotContinuation(b2))
- return 1;
- if (isNotContinuation(src[sp++]))
- return 2;
- return 3;
- }
- assert false;
- return -1;
- }
-
- private static char repl = '\ufffd';
-
- StringCoding.Result decode(byte[] src, int sp, int len) {
- return decode(src, sp, len, result);
- }
-
- static StringCoding.Result decode(byte[] src, int sp, int len,
- StringCoding.Result ret) {
- int sl = sp + len;
- byte[] dst = new byte[len];
- int dp = 0;
- if (COMPACT_STRINGS) { // Latin1 only loop
- while (sp < sl) {
- int b1 = src[sp];
- if (b1 >= 0) {
- dst[dp++] = (byte)b1;
- sp++;
- continue;
- }
- if ((b1 == (byte)0xc2 || b1 == (byte)0xc3) &&
- sp + 1 < sl) {
- int b2 = src[sp + 1];
- if (!isNotContinuation(b2)) {
- dst[dp++] = (byte)(((b1 << 6) ^ b2)^
- (((byte) 0xC0 << 6) ^
- ((byte) 0x80 << 0)));
- sp += 2;
- continue;
- }
- }
- // anything not a latin1, including the repl
- // we have to go with the utf16
- break;
- }
- if (sp == sl) {
- if (dp != dst.length) {
- dst = Arrays.copyOf(dst, dp);
- }
- return ret.with(dst, LATIN1);
- }
- }
- if (dp == 0) {
- dst = new byte[len << 1];
- } else {
- byte[] buf = new byte[len << 1];
- StringLatin1.inflate(dst, 0, buf, 0, dp);
- dst = buf;
- }
- while (sp < sl) {
- int b1 = src[sp++];
- if (b1 >= 0) {
- putChar(dst, dp++, (char) b1);
- } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
- if (sp < sl) {
- int b2 = src[sp++];
- if (isNotContinuation(b2)) {
- putChar(dst, dp++, repl);
- sp--;
- } else {
- putChar(dst, dp++, (char)(((b1 << 6) ^ b2)^
- (((byte) 0xC0 << 6) ^
- ((byte) 0x80 << 0))));
- }
- continue;
- }
- putChar(dst, dp++, repl);
- break;
- } else if ((b1 >> 4) == -2) {
- if (sp + 1 < sl) {
- int b2 = src[sp++];
- int b3 = src[sp++];
- if (isMalformed3(b1, b2, b3)) {
- putChar(dst, dp++, repl);
- sp -= 3;
- sp += malformedN(src, sp, 3);
- } else {
- char c = (char)((b1 << 12) ^
- (b2 << 6) ^
- (b3 ^
- (((byte) 0xE0 << 12) ^
- ((byte) 0x80 << 6) ^
- ((byte) 0x80 << 0))));
- putChar(dst, dp++, isSurrogate(c) ? repl : c);
- }
- continue;
- }
- if (sp < sl && isMalformed3_2(b1, src[sp])) {
- putChar(dst, dp++, repl);
- continue;
- }
- putChar(dst, dp++, repl);
- break;
- } else if ((b1 >> 3) == -2) {
- if (sp + 2 < sl) {
- int b2 = src[sp++];
- int b3 = src[sp++];
- int b4 = src[sp++];
- int uc = ((b1 << 18) ^
- (b2 << 12) ^
- (b3 << 6) ^
- (b4 ^
- (((byte) 0xF0 << 18) ^
- ((byte) 0x80 << 12) ^
- ((byte) 0x80 << 6) ^
- ((byte) 0x80 << 0))));
- if (isMalformed4(b2, b3, b4) ||
- !isSupplementaryCodePoint(uc)) { // shortest form check
- putChar(dst, dp++, repl);
- sp -= 4;
- sp += malformedN(src, sp, 4);
- } else {
- putChar(dst, dp++, highSurrogate(uc));
- putChar(dst, dp++, lowSurrogate(uc));
- }
- continue;
- }
- b1 &= 0xff;
- if (b1 > 0xf4 ||
- sp < sl && isMalformed4_2(b1, src[sp] & 0xff)) {
- putChar(dst, dp++, repl);
- continue;
- }
- sp++;
- putChar(dst, dp++, repl);
- if (sp < sl && isMalformed4_3(src[sp])) {
- continue;
- }
- break;
- } else {
- putChar(dst, dp++, repl);
- }
- }
- if (dp != len) {
- dst = Arrays.copyOf(dst, dp << 1);
- }
- return ret.with(dst, UTF16);
- }
-}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/System.java
--- a/src/java.base/share/classes/java/lang/System.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/System.java Thu Dec 14 12:28:32 2017 +0000
@@ -550,8 +550,10 @@
* System properties. The following properties are guaranteed to be defined:
*
*
java.version
Java version number
+ *
java.version.date
Java version date
*
java.vendor
Java vendor specific string
*
java.vendor.url
Java vendor URL
+ *
java.vendor.version
Java vendor version
*
java.home
Java installation directory
*
java.class.version
Java class version number
*
java.class.path
Java classpath
@@ -591,12 +593,18 @@
*
*
*
java.version
- *
Java Runtime Environment version which may be interpreted
+ *
Java Runtime Environment version, which may be interpreted
* as a {@link Runtime.Version}
+ *
java.version.date
+ *
Java Runtime Environment version date, in ISO-8601 YYYY-MM-DD
+ * format, which may be interpreted as a {@link
+ * java.time.LocalDate}
*
java.vendor
*
Java Runtime Environment vendor
*
java.vendor.url
*
Java vendor URL
+ *
java.vendor.version
+ *
Java vendor version
*
java.home
*
Java installation directory
*
java.vm.specification.version
@@ -2184,6 +2192,15 @@
public Stream layers(ClassLoader loader) {
return ModuleLayer.layers(loader);
}
+
+ public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
+ return StringCoding.newStringUTF8NoRepl(bytes, off, len);
+ }
+
+ public byte[] getBytesUTF8NoRepl(String s) {
+ return StringCoding.getBytesUTF8NoRepl(s);
+ }
+
});
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/VersionProps.java.template
--- a/src/java.base/share/classes/java/lang/VersionProps.java.template Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/VersionProps.java.template Thu Dec 14 12:28:32 2017 +0000
@@ -32,13 +32,15 @@
class VersionProps {
-
private static final String launcher_name =
"@@LAUNCHER_NAME@@";
private static final String java_version =
"@@VERSION_SHORT@@";
+ private static final String java_version_date =
+ "@@VERSION_DATE@@";
+
private static final String java_runtime_name =
"@@RUNTIME_NAME@@";
@@ -57,14 +59,27 @@
private static final String VERSION_OPT =
"@@VERSION_OPT@@";
+ private static final boolean isLTS =
+ "@@VERSION_OPT@@".startsWith("LTS");
+
+ private static final String VENDOR_VERSION_STRING =
+ "@@VENDOR_VERSION_STRING@@";
+
+ private static final String vendor_version =
+ (VENDOR_VERSION_STRING.length() > 0
+ ? " " + VENDOR_VERSION_STRING : "");
+
static {
init();
}
public static void init() {
System.setProperty("java.version", java_version);
+ System.setProperty("java.version.date", java_version_date);
System.setProperty("java.runtime.version", java_runtime_version);
System.setProperty("java.runtime.name", java_runtime_name);
+ if (VENDOR_VERSION_STRING.length() > 0)
+ System.setProperty("java.vendor.version", VENDOR_VERSION_STRING);
}
private static int parseVersionNumber(String version, int prevIndex, int index) {
@@ -162,31 +177,36 @@
/* First line: platform version. */
if (err) {
- ps.println(launcher_name + " version \"" + java_version + "\"");
+ ps.println(launcher_name + " version \"" + java_version + "\""
+ + " " + java_version_date
+ + (isLTS ? " LTS" : ""));
} else {
/* Use a format more in line with GNU conventions */
- ps.println(launcher_name + " " + java_version);
+ ps.println(launcher_name + " " + java_version
+ + " " + java_version_date
+ + (isLTS ? " LTS" : ""));
}
/* Second line: runtime version (ie, libraries). */
String jdk_debug_level = System.getProperty("jdk.debug", "release");
- /* Debug level is not printed for "release" builds */
if ("release".equals(jdk_debug_level)) {
+ /* Do not show debug level "release" builds */
jdk_debug_level = "";
} else {
jdk_debug_level = jdk_debug_level + " ";
}
- ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version);
-
- ps.println(')');
+ ps.println(java_runtime_name + vendor_version
+ + " (" + jdk_debug_level + "build " + java_runtime_version + ")");
/* Third line: JVM information. */
String java_vm_name = System.getProperty("java.vm.name");
String java_vm_version = System.getProperty("java.vm.version");
String java_vm_info = System.getProperty("java.vm.info");
- ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " +
- java_vm_info + ")");
+ ps.println(java_vm_name + vendor_version
+ + " (" + jdk_debug_level + "build " + java_vm_version + ", "
+ + java_vm_info + ")");
+
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/invoke/MethodType.java
--- a/src/java.base/share/classes/java/lang/invoke/MethodType.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/MethodType.java Thu Dec 14 12:28:32 2017 +0000
@@ -105,23 +105,10 @@
private @Stable String methodDescriptor; // cache for toMethodDescriptorString
/**
- * Check the given parameters for validity and store them into the final fields.
+ * Constructor that performs no copying or validation.
+ * Should only be called from the factory method makeImpl
*/
- private MethodType(Class> rtype, Class>[] ptypes, boolean trusted) {
- checkRtype(rtype);
- checkPtypes(ptypes);
- this.rtype = rtype;
- // defensively copy the array passed in by the user
- this.ptypes = trusted ? ptypes : Arrays.copyOf(ptypes, ptypes.length);
- }
-
- /**
- * Construct a temporary unchecked instance of MethodType for use only as a key to the intern table.
- * Does not check the given parameters for validity, and must discarded (if untrusted) or checked
- * (if trusted) after it has been used as a searching key.
- * The parameters are reversed for this constructor, so that it is not accidentally used.
- */
- private MethodType(Class>[] ptypes, Class> rtype) {
+ private MethodType(Class> rtype, Class>[] ptypes) {
this.rtype = rtype;
this.ptypes = ptypes;
}
@@ -308,18 +295,21 @@
if (ptypes.length == 0) {
ptypes = NO_PTYPES; trusted = true;
}
- MethodType primordialMT = new MethodType(ptypes, rtype);
+ MethodType primordialMT = new MethodType(rtype, ptypes);
MethodType mt = internTable.get(primordialMT);
if (mt != null)
return mt;
// promote the object to the Real Thing, and reprobe
+ MethodType.checkRtype(rtype);
if (trusted) {
- MethodType.checkRtype(rtype);
MethodType.checkPtypes(ptypes);
mt = primordialMT;
} else {
- mt = new MethodType(rtype, ptypes, false);
+ // Make defensive copy then validate
+ ptypes = Arrays.copyOf(ptypes, ptypes.length);
+ MethodType.checkPtypes(ptypes);
+ mt = new MethodType(rtype, ptypes);
}
mt.form = MethodTypeForm.findForm(mt);
return internTable.add(mt);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/module/Configuration.java
--- a/src/java.base/share/classes/java/lang/module/Configuration.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/module/Configuration.java Thu Dec 14 12:28:32 2017 +0000
@@ -543,9 +543,8 @@
if (!parents.isEmpty()) {
return configurations()
.skip(1) // skip this configuration
- .map(cf -> cf.nameToModule)
- .filter(map -> map.containsKey(name))
- .map(map -> map.get(name))
+ .map(cf -> cf.nameToModule.get(name))
+ .filter(Objects::nonNull)
.findFirst();
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/lang/module/ModuleDescriptor.java
--- a/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Thu Dec 14 12:28:32 2017 +0000
@@ -39,6 +39,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@@ -2603,7 +2604,8 @@
* Returns a string containing the given set of modifiers and label.
*/
private static String toString(Set mods, String what) {
- return (Stream.concat(mods.stream().map(e -> e.toString().toLowerCase()),
+ return (Stream.concat(mods.stream().map(e -> e.toString()
+ .toLowerCase(Locale.ROOT)),
Stream.of(what)))
.collect(Collectors.joining(" "));
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/SocketInputStream.java
--- a/src/java.base/share/classes/java/net/SocketInputStream.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/SocketInputStream.java Thu Dec 14 12:28:32 2017 +0000
@@ -283,7 +283,7 @@
/**
* Overrides finalize, the fd is closed by the Socket.
*/
- @SuppressWarnings("deprecation")
+ @SuppressWarnings({"deprecation", "removal"})
protected void finalize() {}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/SocketOutputStream.java
--- a/src/java.base/share/classes/java/net/SocketOutputStream.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/SocketOutputStream.java Thu Dec 14 12:28:32 2017 +0000
@@ -175,7 +175,7 @@
/**
* Overrides finalize, the fd is closed by the Socket.
*/
- @SuppressWarnings("deprecation")
+ @SuppressWarnings({"deprecation", "removal"})
protected void finalize() {}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/URLClassLoader.java
--- a/src/java.base/share/classes/java/net/URLClassLoader.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/URLClassLoader.java Thu Dec 14 12:28:32 2017 +0000
@@ -658,8 +658,8 @@
*
* @param name the resource name
* @exception IOException if an I/O exception occurs
- * @return an {@code Enumeration} of {@code URL}s
- * If the loader is closed, the Enumeration will be empty.
+ * @return An {@code Enumeration} of {@code URL}s.
+ * If the loader is closed, the Enumeration contains no elements.
*/
public Enumeration findResources(final String name)
throws IOException
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/URLDecoder.java
--- a/src/java.base/share/classes/java/net/URLDecoder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/URLDecoder.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,10 @@
package java.net;
import java.io.*;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Objects;
/**
* Utility class for HTML form decoding. This class contains static methods
@@ -108,7 +112,43 @@
/**
* Decodes an {@code application/x-www-form-urlencoded} string using
* a specific encoding scheme.
- * The supplied encoding is used to determine
+ *
+ *
+ * This method behaves the same as {@linkplain decode(String s, Charset charset)}
+ * except that it will {@linkplain java.nio.charset.Charset#forName look up the charset}
+ * using the given encoding name.
+ *
+ * @implNote This implementation will throw an {@link java.lang.IllegalArgumentException}
+ * when illegal strings are encountered.
+ *
+ * @param s the {@code String} to decode
+ * @param enc The name of a supported
+ * character
+ * encoding.
+ * @return the newly decoded {@code String}
+ * @throws UnsupportedEncodingException
+ * If character encoding needs to be consulted, but
+ * named character encoding is not supported
+ * @see URLEncoder#encode(java.lang.String, java.lang.String)
+ * @since 1.4
+ */
+ public static String decode(String s, String enc) throws UnsupportedEncodingException {
+ if (enc.length() == 0) {
+ throw new UnsupportedEncodingException ("URLDecoder: empty string enc parameter");
+ }
+
+ try {
+ Charset charset = Charset.forName(enc);
+ return decode(s, charset);
+ } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+ throw new UnsupportedEncodingException(enc);
+ }
+ }
+
+ /**
+ * Decodes an {@code application/x-www-form-urlencoded} string using
+ * a specific {@linkplain java.nio.charset.Charset Charset}.
+ * The supplied charset is used to determine
* what characters are represented by any consecutive sequences of the
* form "{@code %xy}".
*
@@ -118,29 +158,25 @@
* UTF-8 should be used. Not doing so may introduce
* incompatibilities.
*
+ * @implNote This implementation will throw an {@link java.lang.IllegalArgumentException}
+ * when illegal strings are encountered.
+ *
* @param s the {@code String} to decode
- * @param enc The name of a supported
- * character
- * encoding.
+ * @param charset the given charset
* @return the newly decoded {@code String}
- * @exception UnsupportedEncodingException
- * If character encoding needs to be consulted, but
- * named character encoding is not supported
- * @see URLEncoder#encode(java.lang.String, java.lang.String)
- * @since 1.4
+ * @throws NullPointerException if {@code s} or {@code charset} is {@code null}
+ * @throws IllegalArgumentException if the implementation encounters illegal
+ * characters
+ * @see URLEncoder#encode(java.lang.String, java.nio.charset.Charset)
+ * @since 10
*/
- public static String decode(String s, String enc)
- throws UnsupportedEncodingException{
-
+ public static String decode(String s, Charset charset) {
+ Objects.requireNonNull(charset, "Charset");
boolean needToChange = false;
int numChars = s.length();
StringBuilder sb = new StringBuilder(numChars > 500 ? numChars / 2 : numChars);
int i = 0;
- if (enc.length() == 0) {
- throw new UnsupportedEncodingException ("URLDecoder: empty string enc parameter");
- }
-
char c;
byte[] bytes = null;
while (i < numChars) {
@@ -173,7 +209,9 @@
(c=='%')) {
int v = Integer.parseInt(s, i + 1, i + 3, 16);
if (v < 0)
- throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - negative value");
+ throw new IllegalArgumentException(
+ "URLDecoder: Illegal hex characters in escape "
+ + "(%) pattern - negative value");
bytes[pos++] = (byte) v;
i+= 3;
if (i < numChars)
@@ -187,7 +225,7 @@
throw new IllegalArgumentException(
"URLDecoder: Incomplete trailing escape (%) pattern");
- sb.append(new String(bytes, 0, pos, enc));
+ sb.append(new String(bytes, 0, pos, charset));
} catch (NumberFormatException e) {
throw new IllegalArgumentException(
"URLDecoder: Illegal hex characters in escape (%) pattern - "
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/URLEncoder.java
--- a/src/java.base/share/classes/java/net/URLEncoder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/URLEncoder.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,6 +31,7 @@
import java.nio.charset.IllegalCharsetNameException;
import java.nio.charset.UnsupportedCharsetException ;
import java.util.BitSet;
+import java.util.Objects;
import sun.security.action.GetPropertyAction;
/**
@@ -168,45 +169,61 @@
/**
* Translates a string into {@code application/x-www-form-urlencoded}
- * format using a specific encoding scheme. This method uses the
- * supplied encoding scheme to obtain the bytes for unsafe
- * characters.
+ * format using a specific encoding scheme.
*
- * Note: The
- * World Wide Web Consortium Recommendation states that
- * UTF-8 should be used. Not doing so may introduce
- * incompatibilities.
+ * This method behaves the same as {@linkplain encode(String s, Charset charset)}
+ * except that it will {@linkplain java.nio.charset.Charset#forName look up the charset}
+ * using the given encoding name.
*
* @param s {@code String} to be translated.
* @param enc The name of a supported
* character
* encoding.
* @return the translated {@code String}.
- * @exception UnsupportedEncodingException
+ * @throws UnsupportedEncodingException
* If the named encoding is not supported
* @see URLDecoder#decode(java.lang.String, java.lang.String)
* @since 1.4
*/
public static String encode(String s, String enc)
throws UnsupportedEncodingException {
+ if (enc == null) {
+ throw new NullPointerException("charsetName");
+ }
+
+ try {
+ Charset charset = Charset.forName(enc);
+ return encode(s, charset);
+ } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+ throw new UnsupportedEncodingException(enc);
+ }
+ }
+
+ /**
+ * Translates a string into {@code application/x-www-form-urlencoded}
+ * format using a specific {@linkplain java.nio.charset.Charset Charset}.
+ * This method uses the supplied charset to obtain the bytes for unsafe
+ * characters.
+ *
+ * Note: The
+ * World Wide Web Consortium Recommendation states that
+ * UTF-8 should be used. Not doing so may introduce incompatibilities.
+ *
+ * @param s {@code String} to be translated.
+ * @param charset the given charset
+ * @return the translated {@code String}.
+ * @throws NullPointerException if {@code s} or {@code charset} is {@code null}.
+ * @see URLDecoder#decode(java.lang.String, java.nio.charset.Charset)
+ * @since 10
+ */
+ public static String encode(String s, Charset charset) {
+ Objects.requireNonNull(charset, "charset");
boolean needToChange = false;
StringBuilder out = new StringBuilder(s.length());
- Charset charset;
CharArrayWriter charArrayWriter = new CharArrayWriter();
- if (enc == null)
- throw new NullPointerException("charsetName");
-
- try {
- charset = Charset.forName(enc);
- } catch (IllegalCharsetNameException e) {
- throw new UnsupportedEncodingException(enc);
- } catch (UnsupportedCharsetException e) {
- throw new UnsupportedEncodingException(enc);
- }
-
for (int i = 0; i < s.length();) {
int c = (int) s.charAt(i);
//System.out.println("Examining character: " + c);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/net/URLStreamHandler.java
--- a/src/java.base/share/classes/java/net/URLStreamHandler.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/net/URLStreamHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -480,39 +480,14 @@
* @return a string representation of the {@code URL} argument.
*/
protected String toExternalForm(URL u) {
-
- // pre-compute length of StringBuffer
- int len = u.getProtocol().length() + 1;
- if (u.getAuthority() != null && u.getAuthority().length() > 0)
- len += 2 + u.getAuthority().length();
- if (u.getPath() != null) {
- len += u.getPath().length();
- }
- if (u.getQuery() != null) {
- len += 1 + u.getQuery().length();
- }
- if (u.getRef() != null)
- len += 1 + u.getRef().length();
-
- StringBuilder result = new StringBuilder(len);
- result.append(u.getProtocol());
- result.append(":");
- if (u.getAuthority() != null && u.getAuthority().length() > 0) {
- result.append("//");
- result.append(u.getAuthority());
- }
- if (u.getPath() != null) {
- result.append(u.getPath());
- }
- if (u.getQuery() != null) {
- result.append('?');
- result.append(u.getQuery());
- }
- if (u.getRef() != null) {
- result.append("#");
- result.append(u.getRef());
- }
- return result.toString();
+ String s;
+ return u.getProtocol()
+ + ':'
+ + (((s = u.getAuthority()) != null && s.length() > 0)
+ ? "//" + s : "")
+ + (((s = u.getPath()) != null) ? s : "")
+ + (((s = u.getQuery()) != null) ? '?' + s : "")
+ + (((s = u.getRef()) != null) ? '#' + s : "");
}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/nio/channels/Channels.java
--- a/src/java.base/share/classes/java/nio/channels/Channels.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/nio/channels/Channels.java Thu Dec 14 12:28:32 2017 +0000
@@ -527,7 +527,7 @@
* behaves in exactly the same way as the expression
*
*
The reader's default action for malformed-input and unmappable-character
+ * errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
+ * them. When more control over the error handling is required, the constructor
+ * that takes a {@linkplain java.nio.charset.CharsetDecoder} should be used.
+ *
+ * @param ch The channel from which bytes will be read
+ *
+ * @param charset The charset to be used
+ *
+ * @return A new reader
+ */
+ public static Reader newReader(ReadableByteChannel ch, Charset charset) {
+ Objects.requireNonNull(charset, "charset");
+ return newReader(ch, charset.newDecoder(), -1);
+ }
+
+ /**
* Constructs a writer that encodes characters using the given encoder and
* writes the resulting bytes to the given channel.
*
@@ -595,7 +627,7 @@
* behaves in exactly the same way as the expression
*
*
*
* @param ch
@@ -616,4 +648,38 @@
Objects.requireNonNull(csName, "csName");
return newWriter(ch, Charset.forName(csName).newEncoder(), -1);
}
+
+ /**
+ * Constructs a writer that encodes characters according to the given
+ * charset and writes the resulting bytes to the given channel.
+ *
+ *
An invocation of this method of the form
+ *
+ *
{@code
+ * Channels.newWriter(ch, charset)
+ * }
+ *
+ * behaves in exactly the same way as the expression
+ *
+ *
The writer's default action for malformed-input and unmappable-character
+ * errors is to {@linkplain java.nio.charset.CodingErrorAction#REPORT report}
+ * them. When more control over the error handling is required, the constructor
+ * that takes a {@linkplain java.nio.charset.CharsetEncoder} should be used.
+ *
+ * @param ch
+ * The channel to which bytes will be written
+ *
+ * @param charset
+ * The charset to be used
+ *
+ * @return A new writer
+ */
+ public static Writer newWriter(WritableByteChannel ch, Charset charset) {
+ Objects.requireNonNull(charset, "charset");
+ return newWriter(ch, charset.newEncoder(), -1);
}
+}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/security/ProtectionDomain.java
--- a/src/java.base/share/classes/java/security/ProtectionDomain.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/security/ProtectionDomain.java Thu Dec 14 12:28:32 2017 +0000
@@ -25,15 +25,13 @@
package java.security;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.WeakHashMap;
import jdk.internal.misc.JavaSecurityAccess;
import jdk.internal.misc.JavaSecurityProtectionDomainAccess;
import static jdk.internal.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
@@ -115,23 +113,10 @@
}
static {
- // setup SharedSecrets to allow access to doIntersectionPrivilege
- // methods and ProtectionDomain cache
+ // Set up JavaSecurityAccess in SharedSecrets
SharedSecrets.setJavaSecurityAccess(new JavaSecurityAccessImpl());
- SharedSecrets.setJavaSecurityProtectionDomainAccess(
- new JavaSecurityProtectionDomainAccess() {
- @Override
- public ProtectionDomainCache getProtectionDomainCache() {
- return new PDCache();
- }
- });
}
- /**
- * Used for storing ProtectionDomains as keys in a Map.
- */
- static final class Key {}
-
/* CodeSource */
private CodeSource codesource ;
@@ -571,117 +556,27 @@
}
/**
- * A cache of ProtectionDomains and their Permissions.
- *
- * This class stores ProtectionDomains as weak keys in a ConcurrentHashMap
- * with additional support for checking and removing weak keys that are no
- * longer in use. There can be cases where the permission collection may
- * have a chain of strong references back to the ProtectionDomain, which
- * ordinarily would prevent the entry from being removed from the map. To
- * address that, we wrap the permission collection in a SoftReference so
- * that it can be reclaimed by the garbage collector due to memory demand.
+ * Used for storing ProtectionDomains as keys in a Map.
*/
- private static class PDCache implements ProtectionDomainCache {
- private final ConcurrentHashMap>
- pdMap = new ConcurrentHashMap<>();
- private final ReferenceQueue queue = new ReferenceQueue<>();
-
- @Override
- public void put(ProtectionDomain pd, PermissionCollection pc) {
- processQueue(queue, pdMap);
- WeakProtectionDomainKey weakPd =
- new WeakProtectionDomainKey(pd, queue);
- pdMap.put(weakPd, new SoftReference<>(pc));
- }
-
- @Override
- public PermissionCollection get(ProtectionDomain pd) {
- processQueue(queue, pdMap);
- WeakProtectionDomainKey weakPd = new WeakProtectionDomainKey(pd);
- SoftReference sr = pdMap.get(weakPd);
- return (sr == null) ? null : sr.get();
- }
-
- /**
- * Removes weak keys from the map that have been enqueued
- * on the reference queue and are no longer in use.
- */
- private static void processQueue(ReferenceQueue queue,
- ConcurrentHashMap extends
- WeakReference, ?> pdMap) {
- Reference extends Key> ref;
- while ((ref = queue.poll()) != null) {
- pdMap.remove(ref);
- }
- }
- }
-
- /**
- * A weak key for a ProtectionDomain.
- */
- private static class WeakProtectionDomainKey extends WeakReference {
- /**
- * Saved value of the referent's identity hash code, to maintain
- * a consistent hash code after the referent has been cleared
- */
- private final int hash;
+ final class Key {}
- /**
- * A key representing a null ProtectionDomain.
- */
- private static final Key NULL_KEY = new Key();
-
- /**
- * Create a new WeakProtectionDomain with the specified domain and
- * registered with a queue.
- */
- WeakProtectionDomainKey(ProtectionDomain pd, ReferenceQueue rq) {
- this((pd == null ? NULL_KEY : pd.key), rq);
- }
-
- WeakProtectionDomainKey(ProtectionDomain pd) {
- this(pd == null ? NULL_KEY : pd.key);
- }
-
- private WeakProtectionDomainKey(Key key, ReferenceQueue rq) {
- super(key, rq);
- hash = key.hashCode();
- }
-
- private WeakProtectionDomainKey(Key key) {
- super(key);
- hash = key.hashCode();
- }
-
- /**
- * Returns the identity hash code of the original referent.
- */
- @Override
- public int hashCode() {
- return hash;
- }
-
- /**
- * Returns true if the given object is an identical
- * WeakProtectionDomainKey instance, or, if this object's referent
- * has not been cleared and the given object is another
- * WeakProtectionDomainKey instance with an identical non-null
- * referent as this one.
- */
- @Override
- public boolean equals(Object obj) {
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof WeakProtectionDomainKey) {
- Object referent = get();
- return (referent != null) &&
- (referent == ((WeakProtectionDomainKey)obj).get());
- } else {
- return false;
- }
- }
+ static {
+ SharedSecrets.setJavaSecurityProtectionDomainAccess(
+ new JavaSecurityProtectionDomainAccess() {
+ public ProtectionDomainCache getProtectionDomainCache() {
+ return new ProtectionDomainCache() {
+ private final Map map =
+ Collections.synchronizedMap
+ (new WeakHashMap());
+ public void put(ProtectionDomain pd,
+ PermissionCollection pc) {
+ map.put((pd == null ? null : pd.key), pc);
+ }
+ public PermissionCollection get(ProtectionDomain pd) {
+ return pd == null ? map.get(null) : map.get(pd.key);
+ }
+ };
+ }
+ });
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/text/DateFormat.java
--- a/src/java.base/share/classes/java/text/DateFormat.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/text/DateFormat.java Thu Dec 14 12:28:32 2017 +0000
@@ -97,6 +97,13 @@
* DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
* }
*
+ *
+ *
If the specified locale contains "ca" (calendar), "rg" (region override),
+ * and/or "tz" (timezone) Unicode
+ * extensions, the calendar, the country and/or the time zone for formatting
+ * are overridden. If both "ca" and "rg" are specified, the calendar from the "ca"
+ * extension supersedes the implicit one from the "rg" extension.
+ *
*
You can use a DateFormat to parse also.
*
*
{@code
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/text/DateFormatSymbols.java
--- a/src/java.base/share/classes/java/text/DateFormatSymbols.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/text/DateFormatSymbols.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
import java.util.ResourceBundle;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -82,6 +83,10 @@
*
*
*
+ *
If the locale contains "rg" (region override)
+ * Unicode extension,
+ * the symbols are overridden for the designated region.
+ *
*
* DateFormatSymbols objects are cloneable. When you obtain
* a DateFormatSymbols object, feel free to modify the
@@ -716,15 +721,18 @@
}
dfs = new DateFormatSymbols(false);
+ // check for region override
+ Locale override = CalendarDataUtility.findRegionOverride(locale);
+
// Initialize the fields from the ResourceBundle for locale.
LocaleProviderAdapter adapter
- = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, locale);
+ = LocaleProviderAdapter.getAdapter(DateFormatSymbolsProvider.class, override);
// Avoid any potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
ResourceBundle resource
- = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(locale);
+ = ((ResourceBundleBasedAdapter)adapter).getLocaleData().getDateFormatData(override);
dfs.locale = locale;
// JRE and CLDR use different keys
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/text/DecimalFormatSymbols.java
--- a/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/text/DecimalFormatSymbols.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,7 @@
import java.text.spi.DecimalFormatSymbolsProvider;
import java.util.Currency;
import java.util.Locale;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.locale.provider.ResourceBundleBasedAdapter;
@@ -56,6 +57,10 @@
* of these symbols, you can get the DecimalFormatSymbols object from
* your DecimalFormat and modify it.
*
+ *
If the locale contains "rg" (region override)
+ * Unicode extension,
+ * the symbols are overridden for the designated region.
+ *
* @see java.util.Locale
* @see DecimalFormat
* @author Mark Davis
@@ -609,13 +614,18 @@
private void initialize( Locale locale ) {
this.locale = locale;
+ // check for region override
+ Locale override = locale.getUnicodeLocaleType("nu") == null ?
+ CalendarDataUtility.findRegionOverride(locale) :
+ locale;
+
// get resource bundle data
- LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, locale);
+ LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(DecimalFormatSymbolsProvider.class, override);
// Avoid potential recursions
if (!(adapter instanceof ResourceBundleBasedAdapter)) {
adapter = LocaleProviderAdapter.getResourceBundleBased();
}
- Object[] data = adapter.getLocaleResources(locale).getDecimalFormatSymbolsData();
+ Object[] data = adapter.getLocaleResources(override).getDecimalFormatSymbolsData();
String[] numberElements = (String[]) data[0];
decimalSeparator = numberElements[0].charAt(0);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/text/NumberFormat.java
--- a/src/java.base/share/classes/java/text/NumberFormat.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/text/NumberFormat.java Thu Dec 14 12:28:32 2017 +0000
@@ -96,7 +96,14 @@
* NumberFormat nf = NumberFormat.getInstance(Locale.FRENCH);
* }
*
- * You can also use a NumberFormat to parse numbers:
+ *
+ *
If the locale contains "nu" (numbers) and/or "rg" (region override)
+ * Unicode extensions,
+ * the decimal digits, and/or the country used for formatting are overridden.
+ * If both "nu" and "rg" are specified, the decimal digits from the "nu"
+ * extension supersedes the implicit one from the "rg" extension.
+ *
+ *
You can also use a {@code NumberFormat} to parse numbers:
*
*
{@code
* myNumber = nf.parse(myString);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/text/SimpleDateFormat.java
--- a/src/java.base/share/classes/java/text/SimpleDateFormat.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/text/SimpleDateFormat.java Thu Dec 14 12:28:32 2017 +0000
@@ -672,7 +672,7 @@
// However, the calendar should use the current default TimeZone.
// If this is not contained in the locale zone strings, then the zone
// will be formatted using generic GMT+/-H:MM nomenclature.
- calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
+ calendar = Calendar.getInstance(loc);
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/format/DateTimeFormatter.java
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Thu Dec 14 12:28:32 2017 +0000
@@ -97,6 +97,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import sun.util.locale.provider.TimeZoneNameUtility;
/**
* Formatter for printing and parsing date-time objects.
@@ -548,7 +549,7 @@
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
*
* The formatter will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
- * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
+ * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
* Alternatively use the {@link #ofPattern(String, Locale)} variant of this method.
*
* The returned formatter has no override chronology or zone.
@@ -572,7 +573,7 @@
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
*
* The formatter will use the specified locale.
- * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
+ * This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter.
*
* The returned formatter has no override chronology or zone.
* It uses {@link ResolverStyle#SMART SMART} resolver style.
@@ -1443,10 +1444,17 @@
* This is used to lookup any part of the formatter needing specific
* localization, such as the text or localized pattern.
*
+ * The locale is stored as passed in, without further processing.
+ * If the locale has
+ * Unicode extensions, they may be used later in text
+ * processing. To set the chronology, time-zone and decimal style from
+ * unicode extensions, see {@link #localizedBy localizedBy()}.
+ *
* This instance is immutable and unaffected by this method call.
*
* @param locale the new locale, not null
* @return a formatter based on this formatter with the requested locale, not null
+ * @see #localizedBy(Locale)
*/
public DateTimeFormatter withLocale(Locale locale) {
if (this.locale.equals(locale)) {
@@ -1455,6 +1463,52 @@
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
}
+ /**
+ * Returns a copy of this formatter with localized values of the locale,
+ * calendar, region, decimal style and/or timezone, that supercede values in
+ * this formatter.
+ *
+ * This is used to lookup any part of the formatter needing specific
+ * localization, such as the text or localized pattern. If the locale contains the
+ * "ca" (calendar), "nu" (numbering system), "rg" (region override), and/or
+ * "tz" (timezone)
+ * Unicode extensions,
+ * the chronology, numbering system and/or the zone are overridden. If both "ca"
+ * and "rg" are specified, the chronology from the "ca" extension supersedes the
+ * implicit one from the "rg" extension. Same is true for the "nu" extension.
+ *
+ * Unlike the {@link #withLocale withLocale} method, the call to this method may
+ * produce a different formatter depending on the order of method chaining with
+ * other withXXXX() methods.
+ *
+ * This instance is immutable and unaffected by this method call.
+ *
+ * @param locale the locale, not null
+ * @return a formatter based on this formatter with localized values of
+ * the calendar, decimal style and/or timezone, that supercede values in this
+ * formatter.
+ * @see #withLocale(Locale)
+ * @since 10
+ */
+ public DateTimeFormatter localizedBy(Locale locale) {
+ if (this.locale.equals(locale)) {
+ return this;
+ }
+
+ // Check for decimalStyle/chronology/timezone in locale object
+ Chronology c = locale.getUnicodeLocaleType("ca") != null ?
+ Chronology.ofLocale(locale) : chrono;
+ DecimalStyle ds = locale.getUnicodeLocaleType("nu") != null ?
+ DecimalStyle.of(locale) : decimalStyle;
+ String tzType = locale.getUnicodeLocaleType("tz");
+ ZoneId z = tzType != null ?
+ TimeZoneNameUtility.convertLDMLShortID(tzType)
+ .map(ZoneId::of)
+ .orElse(zone) :
+ zone;
+ return new DateTimeFormatter(printerParser, locale, ds, resolverStyle, resolverFields, c, z);
+ }
+
//-----------------------------------------------------------------------
/**
* Gets the DecimalStyle to be used during formatting.
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
--- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -120,6 +120,7 @@
import java.util.concurrent.ConcurrentMap;
import sun.text.spi.JavaTimeDateTimePatternProvider;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
import sun.util.locale.provider.TimeZoneNameUtility;
@@ -198,6 +199,10 @@
* Gets the formatting pattern for date and time styles for a locale and chronology.
* The locale and chronology are used to lookup the locale specific format
* for the requested dateStyle and/or timeStyle.
+ *
+ * If the locale contains the "rg" (region override)
+ * Unicode extensions,
+ * the formatting pattern is overridden with the one appropriate for the region.
*
* @param dateStyle the FormatStyle for the date, null for time-only pattern
* @param timeStyle the FormatStyle for the time, null for date-only pattern
@@ -216,7 +221,8 @@
LocaleProviderAdapter adapter = LocaleProviderAdapter.getAdapter(JavaTimeDateTimePatternProvider.class, locale);
JavaTimeDateTimePatternProvider provider = adapter.getJavaTimeDateTimePatternProvider();
String pattern = provider.getJavaTimeDateTimePattern(convertStyle(timeStyle),
- convertStyle(dateStyle), chrono.getCalendarType(), locale);
+ convertStyle(dateStyle), chrono.getCalendarType(),
+ CalendarDataUtility.findRegionOverride(locale));
return pattern;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/format/DateTimeTextProvider.java
--- a/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/format/DateTimeTextProvider.java Thu Dec 14 12:28:32 2017 +0000
@@ -510,7 +510,8 @@
@SuppressWarnings("unchecked")
static T getLocalizedResource(String key, Locale locale) {
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
- .getLocaleResources(locale);
+ .getLocaleResources(
+ CalendarDataUtility.findRegionOverride(locale));
ResourceBundle rb = lr.getJavaTimeFormatData();
return rb.containsKey(key) ? (T) rb.getObject(key) : null;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/format/DecimalStyle.java
--- a/src/java.base/share/classes/java/time/format/DecimalStyle.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/format/DecimalStyle.java Thu Dec 14 12:28:32 2017 +0000
@@ -147,6 +147,11 @@
* Obtains the DecimalStyle for the specified locale.
*
* This method provides access to locale sensitive decimal style symbols.
+ * If the locale contains "nu" (Numbering System) and/or "rg"
+ * (Region Override)
+ * Unicode extensions, returned instance will reflect the values specified with
+ * those extensions. If both "nu" and "rg" are specified, the value from
+ * the "nu" extension supersedes the implicit one from the "rg" extension.
*
* @param locale the locale, not null
* @return the decimal style, not null
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/temporal/ChronoField.java
--- a/src/java.base/share/classes/java/time/temporal/ChronoField.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/temporal/ChronoField.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,6 +79,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
@@ -632,7 +633,9 @@
}
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
- .getLocaleResources(locale);
+ .getLocaleResources(
+ CalendarDataUtility
+ .findRegionOverride(locale));
ResourceBundle rb = lr.getJavaTimeFormatData();
String key = "field." + displayNameKey;
return rb.containsKey(key) ? rb.getString(key) : name;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/temporal/IsoFields.java
--- a/src/java.base/share/classes/java/time/temporal/IsoFields.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/temporal/IsoFields.java Thu Dec 14 12:28:32 2017 +0000
@@ -81,6 +81,7 @@
import java.util.Objects;
import java.util.ResourceBundle;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
@@ -430,7 +431,9 @@
public String getDisplayName(Locale locale) {
Objects.requireNonNull(locale, "locale");
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
- .getLocaleResources(locale);
+ .getLocaleResources(
+ CalendarDataUtility
+ .findRegionOverride(locale));
ResourceBundle rb = lr.getJavaTimeFormatData();
return rb.containsKey("field.week") ? rb.getString("field.week") : toString();
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/time/temporal/WeekFields.java
--- a/src/java.base/share/classes/java/time/temporal/WeekFields.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/time/temporal/WeekFields.java Thu Dec 14 12:28:32 2017 +0000
@@ -286,13 +286,17 @@
* Obtains an instance of {@code WeekFields} appropriate for a locale.
*
* This will look up appropriate values from the provider of localization data.
+ * If the locale contains "fw" (First day of week) and/or "rg"
+ * (Region Override)
+ * Unicode extensions, returned instance will reflect the values specified with
+ * those extensions. If both "fw" and "rg" are specified, the value from
+ * the "fw" extension supersedes the implicit one from the "rg" extension.
*
* @param locale the locale to use, not null
* @return the week-definition, not null
*/
public static WeekFields of(Locale locale) {
Objects.requireNonNull(locale, "locale");
- locale = new Locale(locale.getLanguage(), locale.getCountry()); // elminate variants
int calDow = CalendarDataUtility.retrieveFirstDayOfWeek(locale);
DayOfWeek dow = DayOfWeek.SUNDAY.plus(calDow - 1);
@@ -1041,7 +1045,8 @@
Objects.requireNonNull(locale, "locale");
if (rangeUnit == YEARS) { // only have values for week-of-year
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
- .getLocaleResources(locale);
+ .getLocaleResources(
+ CalendarDataUtility.findRegionOverride(locale));
ResourceBundle rb = lr.getJavaTimeFormatData();
return rb.containsKey("field.week") ? rb.getString("field.week") : name;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Calendar.java
--- a/src/java.base/share/classes/java/util/Calendar.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Calendar.java Thu Dec 14 12:28:32 2017 +0000
@@ -58,6 +58,7 @@
import sun.util.calendar.ZoneInfo;
import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.TimeZoneNameUtility;
import sun.util.spi.CalendarProvider;
/**
@@ -128,9 +129,14 @@
*
* Calendar defines a locale-specific seven day week using two
* parameters: the first day of the week and the minimal days in first week
- * (from 1 to 7). These numbers are taken from the locale resource data when a
- * Calendar is constructed. They may also be specified explicitly
- * through the methods for setting their values.
+ * (from 1 to 7). These numbers are taken from the locale resource data or the
+ * locale itself when a {@code Calendar} is constructed. If the designated
+ * locale contains "fw" and/or "rg"
+ * Unicode extensions, the first day of the week will be obtained according to
+ * those extensions. If both "fw" and "rg" are specified, the value from the "fw"
+ * extension supersedes the implicit one from the "rg" extension.
+ * They may also be specified explicitly through the methods for setting their
+ * values.
*
*
When setting or getting the WEEK_OF_MONTH or
* WEEK_OF_YEAR fields, Calendar must determine the
@@ -1444,6 +1450,11 @@
*
*
The default values are used for locale and time zone if these
* parameters haven't been given explicitly.
+ *
+ * If the locale contains the time zone with "tz"
+ * Unicode extension,
+ * and time zone hasn't been given explicitly, time zone in the locale
+ * is used.
*
*
Any out of range field values are either normalized in lenient
* mode or detected as an invalid value in non-lenient mode.
@@ -1463,7 +1474,7 @@
locale = Locale.getDefault();
}
if (zone == null) {
- zone = TimeZone.getDefault();
+ zone = defaultTimeZone(locale);
}
Calendar cal;
if (type == null) {
@@ -1605,12 +1616,17 @@
* Calendar returned is based on the current time
* in the default time zone with the default
* {@link Locale.Category#FORMAT FORMAT} locale.
+ *
+ * If the locale contains the time zone with "tz"
+ * Unicode extension,
+ * that time zone is used instead.
*
* @return a Calendar.
*/
public static Calendar getInstance()
{
- return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT));
+ Locale aLocale = Locale.getDefault(Locale.Category.FORMAT);
+ return createCalendar(defaultTimeZone(aLocale), aLocale);
}
/**
@@ -1631,13 +1647,17 @@
* Gets a calendar using the default time zone and specified locale.
* The Calendar returned is based on the current time
* in the default time zone with the given locale.
+ *
+ * If the locale contains the time zone with "tz"
+ * Unicode extension,
+ * that time zone is used instead.
*
* @param aLocale the locale for the week data
* @return a Calendar.
*/
public static Calendar getInstance(Locale aLocale)
{
- return createCalendar(TimeZone.getDefault(), aLocale);
+ return createCalendar(defaultTimeZone(aLocale), aLocale);
}
/**
@@ -1655,6 +1675,16 @@
return createCalendar(zone, aLocale);
}
+ private static TimeZone defaultTimeZone(Locale l) {
+ TimeZone defaultTZ = TimeZone.getDefault();
+ String shortTZID = l.getUnicodeLocaleType("tz");
+ return shortTZID != null ?
+ TimeZoneNameUtility.convertLDMLShortID(shortTZID)
+ .map(TimeZone::getTimeZone)
+ .orElse(defaultTZ) :
+ defaultTZ;
+ }
+
private static Calendar createCalendar(TimeZone zone,
Locale aLocale)
{
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Collections.java
--- a/src/java.base/share/classes/java/util/Collections.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Collections.java Thu Dec 14 12:28:32 2017 +0000
@@ -24,9 +24,10 @@
*/
package java.util;
-import java.io.Serializable;
+
+import java.io.IOException;
import java.io.ObjectOutputStream;
-import java.io.IOException;
+import java.io.Serializable;
import java.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -5164,14 +5165,19 @@
* specified comparator.
* @since 1.5
*/
+ @SuppressWarnings("unchecked")
public static Comparator reverseOrder(Comparator cmp) {
- if (cmp == null)
- return reverseOrder();
-
- if (cmp instanceof ReverseComparator2)
- return ((ReverseComparator2)cmp).cmp;
-
- return new ReverseComparator2<>(cmp);
+ if (cmp == null) {
+ return (Comparator) ReverseComparator.REVERSE_ORDER;
+ } else if (cmp == ReverseComparator.REVERSE_ORDER) {
+ return (Comparator) Comparators.NaturalOrderComparator.INSTANCE;
+ } else if (cmp == Comparators.NaturalOrderComparator.INSTANCE) {
+ return (Comparator) ReverseComparator.REVERSE_ORDER;
+ } else if (cmp instanceof ReverseComparator2) {
+ return ((ReverseComparator2) cmp).cmp;
+ } else {
+ return new ReverseComparator2<>(cmp);
+ }
}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Currency.java
--- a/src/java.base/share/classes/java/util/Currency.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Currency.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,6 @@
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.IOException;
@@ -42,6 +41,7 @@
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.spi.CurrencyNameProvider;
+import sun.util.locale.provider.CalendarDataUtility;
import sun.util.locale.provider.LocaleServiceProviderPool;
import sun.util.logging.PlatformLogger;
@@ -348,6 +348,13 @@
* until December 31, 2001, and the Euro from January 1, 2002, local time
* of the respective countries.
*
+ * If the specified {@code locale} contains "cu" and/or "rg"
+ * Unicode extensions,
+ * the instance returned from this method reflects
+ * the values specified with those extensions. If both "cu" and "rg" are
+ * specified, the currency from the "cu" extension supersedes the implicit one
+ * from the "rg" extension.
+ *
* The method returns null for territories that don't
* have a currency, such as Antarctica.
*
@@ -361,12 +368,19 @@
* is not a supported ISO 3166 country code.
*/
public static Currency getInstance(Locale locale) {
- String country = locale.getCountry();
- if (country == null) {
- throw new NullPointerException();
+ // check for locale overrides
+ String override = locale.getUnicodeLocaleType("cu");
+ if (override != null) {
+ try {
+ return getInstance(override.toUpperCase(Locale.ROOT));
+ } catch (IllegalArgumentException iae) {
+ // override currency is invalid. Fall through.
+ }
}
- if (country.length() != 2) {
+ String country = CalendarDataUtility.findRegionOverride(locale).getCountry();
+
+ if (country == null || !country.matches("^[a-zA-Z]{2}$")) {
throw new IllegalArgumentException();
}
@@ -482,6 +496,12 @@
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
*
+ * If the default {@link Locale.Category#DISPLAY DISPLAY} locale
+ * contains "rg" (region override)
+ * Unicode extension,
+ * the symbol returned from this method reflects
+ * the value specified with that extension.
+ *
* This is equivalent to calling
* {@link #getSymbol(Locale)
* getSymbol(Locale.getDefault(Locale.Category.DISPLAY))}.
@@ -498,6 +518,11 @@
* For example, for the US Dollar, the symbol is "$" if the specified
* locale is the US, while for other locales it may be "US$". If no
* symbol can be determined, the ISO 4217 currency code is returned.
+ *
+ * If the specified {@code locale} contains "rg" (region override)
+ * Unicode extension,
+ * the symbol returned from this method reflects
+ * the value specified with that extension.
*
* @param locale the locale for which a display name for this currency is
* needed
@@ -507,6 +532,7 @@
public String getSymbol(Locale locale) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(CurrencyNameProvider.class);
+ locale = CalendarDataUtility.findRegionOverride(locale);
String symbol = pool.getLocalizedObject(
CurrencyNameGetter.INSTANCE,
locale, currencyCode, SYMBOL);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/EnumSet.java
--- a/src/java.base/share/classes/java/util/EnumSet.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/EnumSet.java Thu Dec 14 12:28:32 2017 +0000
@@ -75,7 +75,6 @@
* @author Josh Bloch
* @since 1.5
* @see EnumMap
- * @serial exclude
*/
@SuppressWarnings("serial") // No serialVersionUID due to usage of
// serial proxy pattern
@@ -85,12 +84,12 @@
/**
* The class of all the elements of this set.
*/
- final Class elementType;
+ final transient Class elementType;
/**
- * All of the values comprising T. (Cached for performance.)
+ * All of the values comprising E. (Cached for performance.)
*/
- final Enum>[] universe;
+ final transient Enum>[] universe;
EnumSet(ClasselementType, Enum>[] universe) {
this.elementType = elementType;
@@ -416,7 +415,7 @@
*
* @serial include
*/
- private static class SerializationProxy >
+ private static class SerializationProxy>
implements java.io.Serializable
{
@@ -441,10 +440,18 @@
elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
}
- // instead of cast to E, we should perhaps use elementType.cast()
- // to avoid injection of forged stream, but it will slow the implementation
+ /**
+ * Returns an {@code EnumSet} object with initial state
+ * held by this proxy.
+ *
+ * @return a {@code EnumSet} object with initial state
+ * held by this proxy
+ */
@SuppressWarnings("unchecked")
private Object readResolve() {
+ // instead of cast to E, we should perhaps use elementType.cast()
+ // to avoid injection of forged stream, but it will slow the
+ // implementation
EnumSet result = EnumSet.noneOf(elementType);
for (Enum> e : elements)
result.add((E)e);
@@ -454,13 +461,24 @@
private static final long serialVersionUID = 362491234563181265L;
}
+ /**
+ * Returns a
+ *
+ * SerializationProxy
+ * representing the state of this instance.
+ *
+ * @return a {@link SerializationProxy}
+ * representing the state of this instance
+ */
Object writeReplace() {
return new SerializationProxy<>(this);
}
- // readObject method for the serialization proxy pattern
- // See Effective Java, Second Ed., Item 78.
- private void readObject(java.io.ObjectInputStream stream)
+ /**
+ * @param s the stream
+ * @throws java.io.InvalidObjectException always
+ */
+ private void readObject(java.io.ObjectInputStream s)
throws java.io.InvalidObjectException {
throw new java.io.InvalidObjectException("Proxy required");
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Formatter.java
--- a/src/java.base/share/classes/java/util/Formatter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Formatter.java Thu Dec 14 12:28:32 2017 +0000
@@ -2137,6 +2137,39 @@
}
/**
+ * Constructs a new formatter with the specified file name, charset, and
+ * locale.
+ *
+ * @param fileName
+ * The name of the file to use as the destination of this
+ * formatter. If the file exists then it will be truncated to
+ * zero size; otherwise, a new file will be created. The output
+ * will be written to the file and is buffered.
+ *
+ * @param charset
+ * A {@linkplain java.nio.charset.Charset charset}
+ *
+ * @param l
+ * The {@linkplain java.util.Locale locale} to apply during
+ * formatting. If {@code l} is {@code null} then no localization
+ * is applied.
+ *
+ * @throws IOException
+ * if an I/O error occurs while opening or creating the file
+ *
+ * @throws SecurityException
+ * If a security manager is present and {@link
+ * SecurityManager#checkWrite checkWrite(fileName)} denies write
+ * access to the file
+ *
+ * @throws NullPointerException
+ * if {@code fileName} or {@code charset} is {@code null}.
+ */
+ public Formatter(String fileName, Charset charset, Locale l) throws IOException {
+ this(Objects.requireNonNull(charset, "charset"), l, new File(fileName));
+ }
+
+ /**
* Constructs a new formatter with the specified file.
*
*
The charset used is the {@linkplain
@@ -2248,6 +2281,40 @@
}
/**
+ * Constructs a new formatter with the specified file, charset, and
+ * locale.
+ *
+ * @param file
+ * The file to use as the destination of this formatter. If the
+ * file exists then it will be truncated to zero size; otherwise,
+ * a new file will be created. The output will be written to the
+ * file and is buffered.
+ *
+ * @param charset
+ * A {@linkplain java.nio.charset.Charset charset}
+ *
+ * @param l
+ * The {@linkplain java.util.Locale locale} to apply during
+ * formatting. If {@code l} is {@code null} then no localization
+ * is applied.
+ *
+ * @throws IOException
+ * if an I/O error occurs while opening or creating the file
+ *
+ * @throws SecurityException
+ * If a security manager is present and {@link
+ * SecurityManager#checkWrite checkWrite(file.getPath())} denies
+ * write access to the file
+ *
+ * @throws NullPointerException
+ * if {@code file} or {@code charset} is {@code null}.
+ */
+ public Formatter(File file, Charset charset, Locale l) throws IOException {
+ this(Objects.requireNonNull(charset, "charset"), l, file);
+ }
+
+
+ /**
* Constructs a new formatter with the specified print stream.
*
*
The locale used is the {@linkplain
@@ -2340,6 +2407,29 @@
this(l, new BufferedWriter(new OutputStreamWriter(os, csn)));
}
+ /**
+ * Constructs a new formatter with the specified output stream, charset,
+ * and locale.
+ *
+ * @param os
+ * The output stream to use as the destination of this formatter.
+ * The output will be buffered.
+ *
+ * @param charset
+ * A {@linkplain java.nio.charset.Charset charset}
+ *
+ * @param l
+ * The {@linkplain java.util.Locale locale} to apply during
+ * formatting. If {@code l} is {@code null} then no localization
+ * is applied.
+ *
+ * @throws NullPointerException
+ * if {@code os} or {@code charset} is {@code null}.
+ */
+ public Formatter(OutputStream os, Charset charset, Locale l) {
+ this(l, new BufferedWriter(new OutputStreamWriter(os, charset)));
+ }
+
private static char getZero(Locale l) {
if ((l != null) && !l.equals(Locale.US)) {
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(l);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Locale.java
--- a/src/java.base/share/classes/java/util/Locale.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Locale.java Thu Dec 14 12:28:32 2017 +0000
@@ -48,6 +48,7 @@
import java.text.MessageFormat;
import java.util.concurrent.ConcurrentHashMap;
import java.util.spi.LocaleNameProvider;
+import java.util.stream.Collectors;
import sun.security.action.GetPropertyAction;
import sun.util.locale.BaseLocale;
@@ -62,6 +63,7 @@
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
import sun.util.locale.provider.LocaleServiceProviderPool;
+import sun.util.locale.provider.TimeZoneNameUtility;
/**
* A Locale object represents a specific geographical, political,
@@ -665,10 +667,12 @@
/**
* Display types for retrieving localized names from the name providers.
*/
- private static final int DISPLAY_LANGUAGE = 0;
- private static final int DISPLAY_COUNTRY = 1;
- private static final int DISPLAY_VARIANT = 2;
- private static final int DISPLAY_SCRIPT = 3;
+ private static final int DISPLAY_LANGUAGE = 0;
+ private static final int DISPLAY_COUNTRY = 1;
+ private static final int DISPLAY_VARIANT = 2;
+ private static final int DISPLAY_SCRIPT = 3;
+ private static final int DISPLAY_UEXT_KEY = 4;
+ private static final int DISPLAY_UEXT_TYPE = 5;
/**
* Private constructor used by getInstance method
@@ -942,11 +946,14 @@
variant = props.getProperty("user.variant", "");
}
- return getInstance(language, script, country, variant, null);
+ return getInstance(language, script, country, variant,
+ getDefaultExtensions(props.getProperty("user.extensions", ""))
+ .orElse(null));
}
private static Locale initDefault(Locale.Category category) {
Properties props = GetPropertyAction.privilegedGetProperties();
+
return getInstance(
props.getProperty(category.languageKey,
defaultLocale.getLanguage()),
@@ -956,7 +963,22 @@
defaultLocale.getCountry()),
props.getProperty(category.variantKey,
defaultLocale.getVariant()),
- null);
+ getDefaultExtensions(props.getProperty(category.extensionsKey, ""))
+ .orElse(defaultLocale.getLocaleExtensions()));
+ }
+
+ private static Optional getDefaultExtensions(String extensionsProp) {
+ LocaleExtensions exts = null;
+
+ try {
+ exts = new InternalLocaleBuilder()
+ .setExtensions(extensionsProp)
+ .getLocaleExtensions();
+ } catch (LocaleSyntaxException e) {
+ // just ignore this incorrect property
+ }
+
+ return Optional.ofNullable(exts);
}
/**
@@ -1771,7 +1793,7 @@
* @exception NullPointerException if inLocale is null
*/
public String getDisplayLanguage(Locale inLocale) {
- return getDisplayString(baseLocale.getLanguage(), inLocale, DISPLAY_LANGUAGE);
+ return getDisplayString(baseLocale.getLanguage(), null, inLocale, DISPLAY_LANGUAGE);
}
/**
@@ -1801,7 +1823,7 @@
* @since 1.7
*/
public String getDisplayScript(Locale inLocale) {
- return getDisplayString(baseLocale.getScript(), inLocale, DISPLAY_SCRIPT);
+ return getDisplayString(baseLocale.getScript(), null, inLocale, DISPLAY_SCRIPT);
}
/**
@@ -1844,29 +1866,24 @@
* @exception NullPointerException if inLocale is null
*/
public String getDisplayCountry(Locale inLocale) {
- return getDisplayString(baseLocale.getRegion(), inLocale, DISPLAY_COUNTRY);
+ return getDisplayString(baseLocale.getRegion(), null, inLocale, DISPLAY_COUNTRY);
}
- private String getDisplayString(String code, Locale inLocale, int type) {
- if (code.length() == 0) {
+ private String getDisplayString(String code, String cat, Locale inLocale, int type) {
+ Objects.requireNonNull(inLocale);
+ Objects.requireNonNull(code);
+
+ if (code.isEmpty()) {
return "";
}
- if (inLocale == null) {
- throw new NullPointerException();
- }
-
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(LocaleNameProvider.class);
- String key = (type == DISPLAY_VARIANT ? "%%"+code : code);
+ String rbKey = (type == DISPLAY_VARIANT ? "%%"+code : code);
String result = pool.getLocalizedObject(
LocaleNameGetter.INSTANCE,
- inLocale, key, type, code);
- if (result != null) {
- return result;
- }
-
- return code;
+ inLocale, rbKey, type, code, cat);
+ return result != null ? result : code;
}
/**
@@ -1894,29 +1911,31 @@
if (baseLocale.getVariant().length() == 0)
return "";
- LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
+ LocaleResources lr = LocaleProviderAdapter
+ .getResourceBundleBased()
+ .getLocaleResources(inLocale);
String names[] = getDisplayVariantArray(inLocale);
// Get the localized patterns for formatting a list, and use
// them to format the list.
return formatList(names,
- lr.getLocaleName("ListPattern"),
lr.getLocaleName("ListCompositionPattern"));
}
/**
* Returns a name for the locale that is appropriate for display to the
* user. This will be the values returned by getDisplayLanguage(),
- * getDisplayScript(), getDisplayCountry(), and getDisplayVariant() assembled
- * into a single string. The non-empty values are used in order,
- * with the second and subsequent names in parentheses. For example:
+ * getDisplayScript(), getDisplayCountry(), getDisplayVariant() and
+ * optional Unicode extensions
+ * assembled into a single string. The non-empty values are used in order, with
+ * the second and subsequent names in parentheses. For example:
*
- * language (script, country, variant)
- * language (country)
- * language (variant)
- * script (country)
- * country
+ * language (script, country, variant(, extension)*)
+ * language (country(, extension)*)
+ * language (variant(, extension)*)
+ * script (country(, extension)*)
+ * country (extension)*
*
* depending on which fields are specified in the locale. If the
* language, script, country, and variant fields are all empty,
@@ -1931,16 +1950,17 @@
/**
* Returns a name for the locale that is appropriate for display
* to the user. This will be the values returned by
- * getDisplayLanguage(), getDisplayScript(),getDisplayCountry(),
- * and getDisplayVariant() assembled into a single string.
- * The non-empty values are used in order,
- * with the second and subsequent names in parentheses. For example:
+ * getDisplayLanguage(), getDisplayScript(),getDisplayCountry()
+ * getDisplayVariant(), and optional
+ * Unicode extensions assembled into a single string. The non-empty
+ * values are used in order, with the second and subsequent names in
+ * parentheses. For example:
*
- * language (script, country, variant)
- * language (country)
- * language (variant)
- * script (country)
- * country
+ * language (script, country, variant(, extension)*)
+ * language (country(, extension)*)
+ * language (variant(, extension)*)
+ * script (country(, extension)*)
+ * country (extension)*
*
* depending on which fields are specified in the locale. If the
* language, script, country, and variant fields are all empty,
@@ -1951,7 +1971,9 @@
* @throws NullPointerException if inLocale is null
*/
public String getDisplayName(Locale inLocale) {
- LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(inLocale);
+ LocaleResources lr = LocaleProviderAdapter
+ .getResourceBundleBased()
+ .getLocaleResources(inLocale);
String languageName = getDisplayLanguage(inLocale);
String scriptName = getDisplayScript(inLocale);
@@ -1960,7 +1982,6 @@
// Get the localized patterns for formatting a display name.
String displayNamePattern = lr.getLocaleName("DisplayNamePattern");
- String listPattern = lr.getLocaleName("ListPattern");
String listCompositionPattern = lr.getLocaleName("ListCompositionPattern");
// The display name consists of a main name, followed by qualifiers.
@@ -1977,7 +1998,7 @@
if (variantNames.length == 0) {
return "";
} else {
- return formatList(variantNames, listPattern, listCompositionPattern);
+ return formatList(variantNames, listCompositionPattern);
}
}
ArrayList names = new ArrayList<>(4);
@@ -1994,6 +2015,16 @@
names.addAll(Arrays.asList(variantNames));
}
+ // add Unicode extensions
+ if (localeExtensions != null) {
+ localeExtensions.getUnicodeLocaleAttributes().stream()
+ .map(key -> getDisplayString(key, null, inLocale, DISPLAY_UEXT_KEY))
+ .forEach(names::add);
+ localeExtensions.getUnicodeLocaleKeys().stream()
+ .map(key -> getDisplayKeyTypeExtensionString(key, lr, inLocale))
+ .forEach(names::add);
+ }
+
// The first one in the main name
mainName = names.get(0);
@@ -2014,7 +2045,7 @@
// list case, but this is more efficient, and we want it to be
// efficient since all the language-only locales will not have any
// qualifiers.
- qualifierNames.length != 0 ? formatList(qualifierNames, listPattern, listCompositionPattern) : null
+ qualifierNames.length != 0 ? formatList(qualifierNames, listCompositionPattern) : null
};
if (displayNamePattern != null) {
@@ -2121,74 +2152,78 @@
// For each variant token, lookup the display name. If
// not found, use the variant name itself.
for (int i=0; i 3) {
- MessageFormat format = new MessageFormat(listCompositionPattern);
- stringList = composeList(format, stringList);
+ if (pattern == null) {
+ return Arrays.stream(stringList).collect(Collectors.joining(","));
}
- // Rebuild the argument list with the list length as the first element
- Object[] args = new Object[stringList.length + 1];
- System.arraycopy(stringList, 0, args, 1, stringList.length);
- args[0] = stringList.length;
-
- // Format it using the pattern in the resource
- MessageFormat format = new MessageFormat(listPattern);
- return format.format(args);
- }
-
- /**
- * Given a list of strings, return a list shortened to three elements.
- * Shorten it by applying the given format to the first two elements
- * recursively.
- * @param format a format which takes two arguments
- * @param list a list of strings
- * @return if the list is three elements or shorter, the same list;
- * otherwise, a new list of three elements.
- */
- private static String[] composeList(MessageFormat format, String[] list) {
- if (list.length <= 3) return list;
-
- // Use the given format to compose the first two elements into one
- String[] listItems = { list[0], list[1] };
- String newItem = format.format(listItems);
-
- // Form a new list one element shorter
- String[] newList = new String[list.length-1];
- System.arraycopy(list, 2, newList, 1, newList.length-1);
- newList[0] = newItem;
-
- // Recurse
- return composeList(format, newList);
+ switch (stringList.length) {
+ case 0:
+ return "";
+ case 1:
+ return stringList[0];
+ default:
+ return Arrays.stream(stringList).reduce("",
+ (s1, s2) -> {
+ if (s1.equals("")) {
+ return s2;
+ }
+ if (s2.equals("")) {
+ return s1;
+ }
+ return MessageFormat.format(pattern, s1, s2);
+ });
+ }
}
// Duplicate of sun.util.locale.UnicodeLocaleExtension.isKey in order to
@@ -2345,9 +2380,10 @@
Locale locale,
String key,
Object... params) {
- assert params.length == 2;
+ assert params.length == 3;
int type = (Integer)params[0];
String code = (String)params[1];
+ String cat = (String)params[2];
switch(type) {
case DISPLAY_LANGUAGE:
@@ -2358,6 +2394,10 @@
return localeNameProvider.getDisplayVariant(code, locale);
case DISPLAY_SCRIPT:
return localeNameProvider.getDisplayScript(code, locale);
+ case DISPLAY_UEXT_KEY:
+ return localeNameProvider.getDisplayUnicodeExtensionKey(code, locale);
+ case DISPLAY_UEXT_TYPE:
+ return localeNameProvider.getDisplayUnicodeExtensionType(code, cat, locale);
default:
assert false; // shouldn't happen
}
@@ -2384,7 +2424,8 @@
DISPLAY("user.language.display",
"user.script.display",
"user.country.display",
- "user.variant.display"),
+ "user.variant.display",
+ "user.extensions.display"),
/**
* Category used to represent the default locale for
@@ -2393,19 +2434,23 @@
FORMAT("user.language.format",
"user.script.format",
"user.country.format",
- "user.variant.format");
+ "user.variant.format",
+ "user.extensions.format");
- Category(String languageKey, String scriptKey, String countryKey, String variantKey) {
+ Category(String languageKey, String scriptKey, String countryKey,
+ String variantKey, String extensionsKey) {
this.languageKey = languageKey;
this.scriptKey = scriptKey;
this.countryKey = countryKey;
this.variantKey = variantKey;
+ this.extensionsKey = extensionsKey;
}
final String languageKey;
final String scriptKey;
final String countryKey;
final String variantKey;
+ final String extensionsKey;
}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Optional.java
--- a/src/java.base/share/classes/java/util/Optional.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Optional.java Thu Dec 14 12:28:32 2017 +0000
@@ -32,8 +32,9 @@
/**
* A container object which may or may not contain a non-{@code null} value.
- * If a value is present, {@code isPresent()} returns {@code true} and
- * {@code get()} returns the value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered empty and
+ * {@code isPresent()} returns {@code false}.
*
*
Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(Object) orElse()}
@@ -137,14 +138,10 @@
* {@code NoSuchElementException}.
*
* @apiNote
- * The methods {@link #orElse(Object) orElse} and
- * {@link #orElseGet(Supplier) orElseGet}
- * are generally preferable to this method, as they return a substitute
- * value if the value is absent, instead of throwing an exception.
+ * The preferred alternative to this method is {@link #orElseThrow()}.
*
* @return the non-{@code null} value described by this {@code Optional}
* @throws NoSuchElementException if no value is present
- * @see Optional#isPresent()
*/
public T get() {
if (value == null) {
@@ -362,6 +359,21 @@
}
/**
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
+ *
+ * @return the non-{@code null} value described by this {@code Optional}
+ * @throws NoSuchElementException if no value is present
+ * @since 10
+ */
+ public T orElseThrow() {
+ if (value == null) {
+ throw new NoSuchElementException("No value present");
+ }
+ return value;
+ }
+
+ /**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/OptionalDouble.java
--- a/src/java.base/share/classes/java/util/OptionalDouble.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/OptionalDouble.java Thu Dec 14 12:28:32 2017 +0000
@@ -30,9 +30,10 @@
import java.util.stream.DoubleStream;
/**
- * A container object which may or may not contain a {@code double} value. If a
- * value is present, {@code isPresent()} returns {@code true} and
- * {@code getAsDouble()} returns the value.
+ * A container object which may or may not contain a {@code double} value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered empty and
+ * {@code isPresent()} returns {@code false}.
*
*
Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(double) orElse()}
@@ -117,14 +118,10 @@
* {@code NoSuchElementException}.
*
* @apiNote
- * The methods {@link #orElse(double) orElse} and
- * {@link #orElseGet(DoubleSupplier) orElseGet}
- * are generally preferable to this method, as they return a substitute
- * value if the value is absent, instead of throwing an exception.
+ * The preferred alternative to this method is {@link #orElseThrow()}.
*
* @return the value described by this {@code OptionalDouble}
* @throws NoSuchElementException if no value is present
- * @see OptionalDouble#isPresent()
*/
public double getAsDouble() {
if (!isPresent) {
@@ -226,6 +223,21 @@
}
/**
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
+ *
+ * @return the value described by this {@code OptionalDouble}
+ * @throws NoSuchElementException if no value is present
+ * @since 10
+ */
+ public double orElseThrow() {
+ if (!isPresent) {
+ throw new NoSuchElementException("No value present");
+ }
+ return value;
+ }
+
+ /**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/OptionalInt.java
--- a/src/java.base/share/classes/java/util/OptionalInt.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/OptionalInt.java Thu Dec 14 12:28:32 2017 +0000
@@ -30,9 +30,10 @@
import java.util.stream.IntStream;
/**
- * A container object which may or may not contain an {@code int} value. If a
- * value is present, {@code isPresent()} returns {@code true} and
- * {@code getAsInt()} returns the value.
+ * A container object which may or may not contain an {@code int} value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered empty and
+ * {@code isPresent()} returns {@code false}.
*
*
Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(int) orElse()}
@@ -117,14 +118,10 @@
* {@code NoSuchElementException}.
*
* @apiNote
- * The methods {@link #orElse(int) orElse} and
- * {@link #orElseGet(IntSupplier) orElseGet}
- * are generally preferable to this method, as they return a substitute
- * value if the value is absent, instead of throwing an exception.
+ * The preferred alternative to this method is {@link #orElseThrow()}.
*
* @return the value described by this {@code OptionalInt}
* @throws NoSuchElementException if no value is present
- * @see OptionalInt#isPresent()
*/
public int getAsInt() {
if (!isPresent) {
@@ -225,6 +222,21 @@
}
/**
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
+ *
+ * @return the value described by this {@code OptionalInt}
+ * @throws NoSuchElementException if no value is present
+ * @since 10
+ */
+ public int orElseThrow() {
+ if (!isPresent) {
+ throw new NoSuchElementException("No value present");
+ }
+ return value;
+ }
+
+ /**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/OptionalLong.java
--- a/src/java.base/share/classes/java/util/OptionalLong.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/OptionalLong.java Thu Dec 14 12:28:32 2017 +0000
@@ -30,9 +30,10 @@
import java.util.stream.LongStream;
/**
- * A container object which may or may not contain a {@code long} value. If a
- * value is present, {@code isPresent()} returns {@code true} and
- * {@code getAsLong()} returns the value.
+ * A container object which may or may not contain a {@code long} value.
+ * If a value is present, {@code isPresent()} returns {@code true}. If no
+ * value is present, the object is considered empty and
+ * {@code isPresent()} returns {@code false}.
*
*
Additional methods that depend on the presence or absence of a contained
* value are provided, such as {@link #orElse(long) orElse()}
@@ -117,14 +118,10 @@
* {@code NoSuchElementException}.
*
* @apiNote
- * The methods {@link #orElse(long) orElse} and
- * {@link #orElseGet(LongSupplier) orElseGet}
- * are generally preferable to this method, as they return a substitute
- * value if the value is absent, instead of throwing an exception.
+ * The preferred alternative to this method is {@link #orElseThrow()}.
*
* @return the value described by this {@code OptionalLong}
* @throws NoSuchElementException if no value is present
- * @see OptionalLong#isPresent()
*/
public long getAsLong() {
if (!isPresent) {
@@ -225,6 +222,21 @@
}
/**
+ * If a value is present, returns the value, otherwise throws
+ * {@code NoSuchElementException}.
+ *
+ * @return the value described by this {@code OptionalLong}
+ * @throws NoSuchElementException if no value is present
+ * @since 10
+ */
+ public long orElseThrow() {
+ if (!isPresent) {
+ throw new NoSuchElementException("No value present");
+ }
+ return value;
+ }
+
+ /**
* If a value is present, returns the value, otherwise throws an exception
* produced by the exception supplying function.
*
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Properties.java
--- a/src/java.base/share/classes/java/util/Properties.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Properties.java Thu Dec 14 12:28:32 2017 +0000
@@ -37,6 +37,10 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StreamCorruptedException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.IllegalCharsetNameException;
+import java.nio.charset.UnsupportedCharsetException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
@@ -997,6 +1001,11 @@
*
*
The specified stream remains open after this method returns.
*
+ *
This method behaves the same as
+ * {@linkplain #storeToXML(OutputStream os, String comment, Charset charset)}
+ * except that it will {@linkplain java.nio.charset.Charset#forName look up the charset}
+ * using the given encoding name.
+ *
* @param os the output stream on which to emit the XML document.
* @param comment a description of the property list, or {@code null}
* if no comment is desired.
@@ -1011,20 +1020,67 @@
* @throws NullPointerException if {@code os} is {@code null},
* or if {@code encoding} is {@code null}.
* @throws ClassCastException if this {@code Properties} object
- * contains any keys or values that are not
- * {@code Strings}.
+ * contains any keys or values that are not {@code Strings}.
* @see #loadFromXML(InputStream)
* @see Character
* Encoding in Entities
* @since 1.5
*/
public void storeToXML(OutputStream os, String comment, String encoding)
- throws IOException
- {
+ throws IOException {
Objects.requireNonNull(os);
Objects.requireNonNull(encoding);
+
+ try {
+ Charset charset = Charset.forName(encoding);
+ storeToXML(os, comment, charset);
+ } catch (IllegalCharsetNameException | UnsupportedCharsetException e) {
+ throw new UnsupportedEncodingException(encoding);
+ }
+ }
+
+ /**
+ * Emits an XML document representing all of the properties contained
+ * in this table, using the specified encoding.
+ *
+ *
The XML document will have the following DOCTYPE declaration:
+ *
+ * <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+ *
+ *
+ *
If the specified comment is {@code null} then no comment
+ * will be stored in the document.
+ *
+ *
An implementation is required to support writing of XML documents
+ * that use the "{@code UTF-8}" or "{@code UTF-16}" encoding. An
+ * implementation may support additional encodings.
+ *
+ *
Unmappable characters for the specified charset will be encoded as
+ * numeric character references.
+ *
+ *
The specified stream remains open after this method returns.
+ *
+ * @param os the output stream on which to emit the XML document.
+ * @param comment a description of the property list, or {@code null}
+ * if no comment is desired.
+ * @param charset the charset
+ *
+ * @throws IOException if writing to the specified output stream
+ * results in an {@code IOException}.
+ * @throws NullPointerException if {@code os} or {@code charset} is {@code null}.
+ * @throws ClassCastException if this {@code Properties} object
+ * contains any keys or values that are not {@code Strings}.
+ * @see #loadFromXML(InputStream)
+ * @see Character
+ * Encoding in Entities
+ * @since 10
+ */
+ public void storeToXML(OutputStream os, String comment, Charset charset)
+ throws IOException {
+ Objects.requireNonNull(os, "OutputStream");
+ Objects.requireNonNull(charset, "Charset");
PropertiesDefaultHandler handler = new PropertiesDefaultHandler();
- handler.store(this, os, comment, encoding);
+ handler.store(this, os, comment, charset);
}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/Scanner.java
--- a/src/java.base/share/classes/java/util/Scanner.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/Scanner.java Thu Dec 14 12:28:32 2017 +0000
@@ -33,10 +33,13 @@
import java.nio.file.Path;
import java.nio.file.Files;
import java.text.*;
+import java.text.spi.NumberFormatProvider;
import java.util.function.Consumer;
import java.util.regex.*;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.ResourceBundleBasedAdapter;
/**
* A simple text scanner which can parse primitive types and strings using
@@ -575,7 +578,21 @@
* does not exist
*/
public Scanner(InputStream source, String charsetName) {
- this(makeReadable(Objects.requireNonNull(source, "source"), toCharset(charsetName)),
+ this(source, toCharset(charsetName));
+ }
+
+ /**
+ * Constructs a new {@code Scanner} that produces values scanned
+ * from the specified input stream. Bytes from the stream are converted
+ * into characters using the specified charset.
+ *
+ * @param source an input stream to be scanned
+ * @param charset the charset used to convert bytes from the file
+ * into characters to be scanned
+ * @since 10
+ */
+ public Scanner(InputStream source, Charset charset) {
+ this(makeReadable(Objects.requireNonNull(source, "source"), charset),
WHITESPACE_PATTERN);
}
@@ -594,7 +611,18 @@
}
}
+ /*
+ * This method is added so that null-check on charset can be performed before
+ * creating InputStream as an existing test required it.
+ */
+ private static Readable makeReadable(Path source, Charset charset)
+ throws IOException {
+ Objects.requireNonNull(charset, "charset");
+ return makeReadable(Files.newInputStream(source), charset);
+ }
+
private static Readable makeReadable(InputStream source, Charset charset) {
+ Objects.requireNonNull(charset, "charset");
return new InputStreamReader(source, charset);
}
@@ -629,6 +657,22 @@
this(Objects.requireNonNull(source), toDecoder(charsetName));
}
+ /**
+ * Constructs a new {@code Scanner} that produces values scanned
+ * from the specified file. Bytes from the file are converted into
+ * characters using the specified charset.
+ *
+ * @param source A file to be scanned
+ * @param charset The charset used to convert bytes from the file
+ * into characters to be scanned
+ * @throws IOException
+ * if an I/O error occurs opening the source
+ * @since 10
+ */
+ public Scanner(File source, Charset charset) throws IOException {
+ this(Objects.requireNonNull(source), charset.newDecoder());
+ }
+
private Scanner(File source, CharsetDecoder dec)
throws FileNotFoundException
{
@@ -649,6 +693,12 @@
return Channels.newReader(source, dec, -1);
}
+ private static Readable makeReadable(ReadableByteChannel source,
+ Charset charset) {
+ Objects.requireNonNull(charset, "charset");
+ return Channels.newReader(source, charset);
+ }
+
/**
* Constructs a new {@code Scanner} that produces values scanned
* from the specified file. Bytes from the file are converted into
@@ -688,8 +738,22 @@
this(Objects.requireNonNull(source), toCharset(charsetName));
}
- private Scanner(Path source, Charset charset) throws IOException {
- this(makeReadable(Files.newInputStream(source), charset));
+ /**
+ * Constructs a new {@code Scanner} that produces values scanned
+ * from the specified file. Bytes from the file are converted into
+ * characters using the specified charset.
+ *
+ * @param source
+ * the path to the file to be scanned
+ * @param charset
+ * the charset used to convert bytes from the file
+ * into characters to be scanned
+ * @throws IOException
+ * if an I/O error occurs opening the source
+ * @since 10
+ */
+ public Scanner(Path source, Charset charset) throws IOException {
+ this(makeReadable(source, charset));
}
/**
@@ -735,6 +799,21 @@
WHITESPACE_PATTERN);
}
+ /**
+ * Constructs a new {@code Scanner} that produces values scanned
+ * from the specified channel. Bytes from the source are converted into
+ * characters using the specified charset.
+ *
+ * @param source a channel to scan
+ * @param charset the encoding type used to convert bytes from the
+ * channel into characters to be scanned
+ * @since 10
+ */
+ public Scanner(ReadableByteChannel source, Charset charset) {
+ this(makeReadable(Objects.requireNonNull(source, "source"), charset),
+ WHITESPACE_PATTERN);
+ }
+
// Private primitives used to support scanning
private void saveState() {
@@ -1186,9 +1265,27 @@
modCount++;
this.locale = locale;
- DecimalFormat df =
- (DecimalFormat)NumberFormat.getNumberInstance(locale);
+
+ DecimalFormat df = null;
+ NumberFormat nf = NumberFormat.getNumberInstance(locale);
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);
+ if (nf instanceof DecimalFormat) {
+ df = (DecimalFormat) nf;
+ } else {
+
+ // In case where NumberFormat.getNumberInstance() returns
+ // other instance (non DecimalFormat) based on the provider
+ // used and java.text.spi.NumberFormatProvider implementations,
+ // DecimalFormat constructor is used to obtain the instance
+ LocaleProviderAdapter adapter = LocaleProviderAdapter
+ .getAdapter(NumberFormatProvider.class, locale);
+ if (!(adapter instanceof ResourceBundleBasedAdapter)) {
+ adapter = LocaleProviderAdapter.getResourceBundleBased();
+ }
+ String[] all = adapter.getLocaleResources(locale)
+ .getNumberPatterns();
+ df = new DecimalFormat(all[0], dfs);
+ }
// These must be literalized to avoid collision with regex
// metacharacters such as dot or parenthesis
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/SimpleTimeZone.java
--- a/src/java.base/share/classes/java/util/SimpleTimeZone.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/SimpleTimeZone.java Thu Dec 14 12:28:32 2017 +0000
@@ -548,12 +548,11 @@
computeOffset:
if (useDaylight) {
- synchronized (this) {
- if (cacheStart != 0) {
- if (date >= cacheStart && date < cacheEnd) {
- offset += dstSavings;
- break computeOffset;
- }
+ Cache cache = this.cache;
+ if (cache != null) {
+ if (date >= cache.start && date < cache.end) {
+ offset += dstSavings;
+ break computeOffset;
}
}
BaseCalendar cal = date >= GregorianCalendar.DEFAULT_GREGORIAN_CUTOVER ?
@@ -671,14 +670,13 @@
}
private int getOffset(BaseCalendar cal, BaseCalendar.Date cdate, int year, long time) {
- synchronized (this) {
- if (cacheStart != 0) {
- if (time >= cacheStart && time < cacheEnd) {
- return rawOffset + dstSavings;
- }
- if (year == cacheYear) {
- return rawOffset;
- }
+ Cache cache = this.cache;
+ if (cache != null) {
+ if (time >= cache.start && time < cache.end) {
+ return rawOffset + dstSavings;
+ }
+ if (year == cache.year) {
+ return rawOffset;
}
}
@@ -689,11 +687,7 @@
if (time >= start && time < end) {
offset += dstSavings;
}
- synchronized (this) {
- cacheYear = year;
- cacheStart = start;
- cacheEnd = end;
- }
+ this.cache = new Cache(year, start, end);
} else {
if (time < end) {
// TODO: support Gregorian cutover. The previous year
@@ -711,12 +705,7 @@
}
}
if (start <= end) {
- synchronized (this) {
- // The start and end transitions are in multiple years.
- cacheYear = (long) startYear - 1;
- cacheStart = start;
- cacheEnd = end;
- }
+ this.cache = new Cache((long) startYear - 1, start, end);
}
}
return offset;
@@ -876,7 +865,7 @@
* Generates the hash code for the SimpleDateFormat object.
* @return the hash code for this object
*/
- public synchronized int hashCode()
+ public int hashCode()
{
return startMonth ^ startDay ^ startDayOfWeek ^ startTime ^
endMonth ^ endDay ^ endDayOfWeek ^ endTime ^ rawOffset;
@@ -1201,19 +1190,27 @@
/**
* Cache values representing a single period of daylight saving
- * time. When the cache values are valid, cacheStart is the start
- * time (inclusive) of daylight saving time and cacheEnd is the
- * end time (exclusive).
+ * time. Cache.start is the start time (inclusive) of daylight
+ * saving time and Cache.end is the end time (exclusive).
*
- * cacheYear has a year value if both cacheStart and cacheEnd are
- * in the same year. cacheYear is set to startYear - 1 if
- * cacheStart and cacheEnd are in different years. cacheStart is 0
- * if the cache values are void. cacheYear is a long to support
- * Integer.MIN_VALUE - 1 (JCK requirement).
+ * Cache.year has a year value if both Cache.start and Cache.end are
+ * in the same year. Cache.year is set to startYear - 1 if
+ * Cache.start and Cache.end are in different years.
+ * Cache.year is a long to support Integer.MIN_VALUE - 1 (JCK requirement).
*/
- private transient long cacheYear;
- private transient long cacheStart;
- private transient long cacheEnd;
+ private static final class Cache {
+ final long year;
+ final long start;
+ final long end;
+
+ Cache(long year, long start, long end) {
+ this.year = year;
+ this.start = start;
+ this.end = end;
+ }
+ }
+
+ private transient volatile Cache cache;
/**
* Constants specifying values of startMode and endMode.
@@ -1282,9 +1279,8 @@
// Maximum number of rules.
private static final int MAX_RULE_NUM = 6;
- private synchronized void invalidateCache() {
- cacheYear = startYear - 1;
- cacheStart = cacheEnd = 0;
+ private void invalidateCache() {
+ cache = null;
}
//----------------------------------------------------------------------
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/CountedCompleter.java
--- a/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java Thu Dec 14 12:28:32 2017 +0000
@@ -735,7 +735,7 @@
CountedCompleter> a = this, s = a;
while (a.onExceptionalCompletion(ex, s) &&
(a = (s = a).completer) != null && a.status >= 0 &&
- a.recordExceptionalCompletion(ex) == EXCEPTIONAL)
+ isExceptionalStatus(a.recordExceptionalCompletion(ex)))
;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java
--- a/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java Thu Dec 14 12:28:32 2017 +0000
@@ -219,52 +219,59 @@
* methods in a way that flows well in javadocs.
*/
- /*
+ /**
* The status field holds run control status bits packed into a
- * single int to minimize footprint and to ensure atomicity (via
- * CAS). Status is initially zero, and takes on nonnegative
- * values until completed, upon which status (anded with
- * DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks
- * undergoing blocking waits by other threads have the SIGNAL bit
- * set. Completion of a stolen task with SIGNAL set awakens any
- * waiters via notifyAll. Even though suboptimal for some
- * purposes, we use basic builtin wait/notify to take advantage of
- * "monitor inflation" in JVMs that we would otherwise need to
- * emulate to avoid adding further per-task bookkeeping overhead.
- * We want these monitors to be "fat", i.e., not use biasing or
- * thin-lock techniques, so use some odd coding idioms that tend
- * to avoid them, mainly by arranging that every synchronized
- * block performs a wait, notifyAll or both.
+ * single int to ensure atomicity. Status is initially zero, and
+ * takes on nonnegative values until completed, upon which it
+ * holds (sign bit) DONE, possibly with ABNORMAL (cancelled or
+ * exceptional) and THROWN (in which case an exception has been
+ * stored). Tasks with dependent blocked waiting joiners have the
+ * SIGNAL bit set. Completion of a task with SIGNAL set awakens
+ * any waiters via notifyAll. (Waiters also help signal others
+ * upon completion.)
*
* These control bits occupy only (some of) the upper half (16
* bits) of status field. The lower bits are used for user-defined
* tags.
*/
+ volatile int status; // accessed directly by pool and workers
- /** The run status of this task */
- volatile int status; // accessed directly by pool and workers
- static final int DONE_MASK = 0xf0000000; // mask out non-completion bits
- static final int NORMAL = 0xf0000000; // must be negative
- static final int CANCELLED = 0xc0000000; // must be < NORMAL
- static final int EXCEPTIONAL = 0x80000000; // must be < CANCELLED
- static final int SIGNAL = 0x00010000; // must be >= 1 << 16
- static final int SMASK = 0x0000ffff; // short bits for tags
+ private static final int DONE = 1 << 31; // must be negative
+ private static final int ABNORMAL = 1 << 18; // set atomically with DONE
+ private static final int THROWN = 1 << 17; // set atomically with ABNORMAL
+ private static final int SIGNAL = 1 << 16; // true if joiner waiting
+ private static final int SMASK = 0xffff; // short bits for tags
+
+ static boolean isExceptionalStatus(int s) { // needed by subclasses
+ return (s & THROWN) != 0;
+ }
/**
- * Marks completion and wakes up threads waiting to join this
- * task.
+ * Sets DONE status and wakes up threads waiting to join this task.
*
- * @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
- * @return completion status on exit
+ * @return status on exit
*/
- private int setCompletion(int completion) {
- for (int s;;) {
+ private int setDone() {
+ int s;
+ if (((s = (int)STATUS.getAndBitwiseOr(this, DONE)) & SIGNAL) != 0)
+ synchronized (this) { notifyAll(); }
+ return s | DONE;
+ }
+
+ /**
+ * Marks cancelled or exceptional completion unless already done.
+ *
+ * @param completion must be DONE | ABNORMAL, ORed with THROWN if exceptional
+ * @return status on exit
+ */
+ private int abnormalCompletion(int completion) {
+ for (int s, ns;;) {
if ((s = status) < 0)
return s;
- if (STATUS.compareAndSet(this, s, s | completion)) {
- if ((s >>> 16) != 0)
+ else if (STATUS.weakCompareAndSet(this, s, ns = s | completion)) {
+ if ((s & SIGNAL) != 0)
synchronized (this) { notifyAll(); }
- return completion;
+ return ns;
}
}
}
@@ -282,10 +289,11 @@
try {
completed = exec();
} catch (Throwable rex) {
- return setExceptionalCompletion(rex);
+ completed = false;
+ s = setExceptionalCompletion(rex);
}
if (completed)
- s = setCompletion(NORMAL);
+ s = setDone();
}
return s;
}
@@ -297,9 +305,7 @@
* @param timeout using Object.wait conventions.
*/
final void internalWait(long timeout) {
- int s;
- if ((s = status) >= 0 && // force completer to issue notify
- STATUS.compareAndSet(this, s, s | SIGNAL)) {
+ if ((int)STATUS.getAndBitwiseOr(this, SIGNAL) >= 0) {
synchronized (this) {
if (status >= 0)
try { wait(timeout); } catch (InterruptedException ie) { }
@@ -314,27 +320,24 @@
* @return status upon completion
*/
private int externalAwaitDone() {
- int s = ((this instanceof CountedCompleter) ? // try helping
- ForkJoinPool.common.externalHelpComplete(
- (CountedCompleter>)this, 0) :
- ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
- if (s >= 0 && (s = status) >= 0) {
+ int s = tryExternalHelp();
+ if (s >= 0 && (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
boolean interrupted = false;
- do {
- if (STATUS.compareAndSet(this, s, s | SIGNAL)) {
- synchronized (this) {
- if (status >= 0) {
- try {
- wait(0L);
- } catch (InterruptedException ie) {
- interrupted = true;
- }
+ synchronized (this) {
+ for (;;) {
+ if ((s = status) >= 0) {
+ try {
+ wait(0L);
+ } catch (InterruptedException ie) {
+ interrupted = true;
}
- else
- notifyAll();
+ }
+ else {
+ notifyAll();
+ break;
}
}
- } while ((s = status) >= 0);
+ }
if (interrupted)
Thread.currentThread().interrupt();
}
@@ -345,30 +348,40 @@
* Blocks a non-worker-thread until completion or interruption.
*/
private int externalInterruptibleAwaitDone() throws InterruptedException {
- int s;
- if (Thread.interrupted())
- throw new InterruptedException();
- if ((s = status) >= 0 &&
- (s = ((this instanceof CountedCompleter) ?
- ForkJoinPool.common.externalHelpComplete(
- (CountedCompleter>)this, 0) :
- ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
- 0)) >= 0) {
- while ((s = status) >= 0) {
- if (STATUS.compareAndSet(this, s, s | SIGNAL)) {
- synchronized (this) {
- if (status >= 0)
- wait(0L);
- else
- notifyAll();
+ int s = tryExternalHelp();
+ if (s >= 0 && (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
+ synchronized (this) {
+ for (;;) {
+ if ((s = status) >= 0)
+ wait(0L);
+ else {
+ notifyAll();
+ break;
}
}
}
}
+ else if (Thread.interrupted())
+ throw new InterruptedException();
return s;
}
/**
+ * Tries to help with tasks allowed for external callers.
+ *
+ * @return current status
+ */
+ private int tryExternalHelp() {
+ int s;
+ return ((s = status) < 0 ? s:
+ (this instanceof CountedCompleter) ?
+ ForkJoinPool.common.externalHelpComplete(
+ (CountedCompleter>)this, 0) :
+ ForkJoinPool.common.tryExternalUnpush(this) ?
+ doExec() : 0);
+ }
+
+ /**
* Implementation for join, get, quietlyJoin. Directly handles
* only cases of already-completed, external wait, and
* unfork+exec. Others are relayed to ForkJoinPool.awaitJoin.
@@ -475,7 +488,7 @@
} finally {
lock.unlock();
}
- s = setCompletion(EXCEPTIONAL);
+ s = abnormalCompletion(DONE | ABNORMAL | THROWN);
}
return s;
}
@@ -487,7 +500,7 @@
*/
private int setExceptionalCompletion(Throwable ex) {
int s = recordExceptionalCompletion(ex);
- if ((s & DONE_MASK) == EXCEPTIONAL)
+ if ((s & THROWN) != 0)
internalPropagateException(ex);
return s;
}
@@ -662,10 +675,8 @@
* Throws exception, if any, associated with the given status.
*/
private void reportException(int s) {
- if (s == CANCELLED)
- throw new CancellationException();
- if (s == EXCEPTIONAL)
- rethrow(getThrowableException());
+ rethrow((s & THROWN) != 0 ? getThrowableException() :
+ new CancellationException());
}
// public methods
@@ -707,7 +718,7 @@
*/
public final V join() {
int s;
- if ((s = doJoin() & DONE_MASK) != NORMAL)
+ if (((s = doJoin()) & ABNORMAL) != 0)
reportException(s);
return getRawResult();
}
@@ -722,7 +733,7 @@
*/
public final V invoke() {
int s;
- if ((s = doInvoke() & DONE_MASK) != NORMAL)
+ if (((s = doInvoke()) & ABNORMAL) != 0)
reportException(s);
return getRawResult();
}
@@ -747,9 +758,9 @@
public static void invokeAll(ForkJoinTask> t1, ForkJoinTask> t2) {
int s1, s2;
t2.fork();
- if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL)
+ if (((s1 = t1.doInvoke()) & ABNORMAL) != 0)
t1.reportException(s1);
- if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL)
+ if (((s2 = t2.doJoin()) & ABNORMAL) != 0)
t2.reportException(s2);
}
@@ -779,7 +790,7 @@
}
else if (i != 0)
t.fork();
- else if (t.doInvoke() < NORMAL && ex == null)
+ else if ((t.doInvoke() & ABNORMAL) != 0 && ex == null)
ex = t.getException();
}
for (int i = 1; i <= last; ++i) {
@@ -787,7 +798,7 @@
if (t != null) {
if (ex != null)
t.cancel(false);
- else if (t.doJoin() < NORMAL)
+ else if ((t.doJoin() & ABNORMAL) != 0)
ex = t.getException();
}
}
@@ -831,7 +842,7 @@
}
else if (i != 0)
t.fork();
- else if (t.doInvoke() < NORMAL && ex == null)
+ else if ((t.doInvoke() & ABNORMAL) != 0 && ex == null)
ex = t.getException();
}
for (int i = 1; i <= last; ++i) {
@@ -839,7 +850,7 @@
if (t != null) {
if (ex != null)
t.cancel(false);
- else if (t.doJoin() < NORMAL)
+ else if ((t.doJoin() & ABNORMAL) != 0)
ex = t.getException();
}
}
@@ -876,7 +887,8 @@
* @return {@code true} if this task is now cancelled
*/
public boolean cancel(boolean mayInterruptIfRunning) {
- return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED;
+ int s = abnormalCompletion(DONE | ABNORMAL);
+ return (s & (ABNORMAL | THROWN)) == ABNORMAL;
}
public final boolean isDone() {
@@ -884,7 +896,7 @@
}
public final boolean isCancelled() {
- return (status & DONE_MASK) == CANCELLED;
+ return (status & (ABNORMAL | THROWN)) == ABNORMAL;
}
/**
@@ -893,7 +905,7 @@
* @return {@code true} if this task threw an exception or was cancelled
*/
public final boolean isCompletedAbnormally() {
- return status < NORMAL;
+ return (status & ABNORMAL) != 0;
}
/**
@@ -904,7 +916,7 @@
* exception and was not cancelled
*/
public final boolean isCompletedNormally() {
- return (status & DONE_MASK) == NORMAL;
+ return (status & (DONE | ABNORMAL)) == DONE;
}
/**
@@ -915,9 +927,9 @@
* @return the exception, or {@code null} if none
*/
public final Throwable getException() {
- int s = status & DONE_MASK;
- return ((s >= NORMAL) ? null :
- (s == CANCELLED) ? new CancellationException() :
+ int s = status;
+ return ((s & ABNORMAL) == 0 ? null :
+ (s & THROWN) == 0 ? new CancellationException() :
getThrowableException());
}
@@ -961,7 +973,7 @@
setExceptionalCompletion(rex);
return;
}
- setCompletion(NORMAL);
+ setDone();
}
/**
@@ -973,7 +985,7 @@
* @since 1.8
*/
public final void quietlyComplete() {
- setCompletion(NORMAL);
+ setDone();
}
/**
@@ -990,11 +1002,12 @@
public final V get() throws InterruptedException, ExecutionException {
int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
doJoin() : externalInterruptibleAwaitDone();
- if ((s &= DONE_MASK) == CANCELLED)
+ if ((s & THROWN) != 0)
+ throw new ExecutionException(getThrowableException());
+ else if ((s & ABNORMAL) != 0)
throw new CancellationException();
- if (s == EXCEPTIONAL)
- throw new ExecutionException(getThrowableException());
- return getRawResult();
+ else
+ return getRawResult();
}
/**
@@ -1034,7 +1047,7 @@
while ((s = status) >= 0 &&
(ns = deadline - System.nanoTime()) > 0L) {
if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
- STATUS.compareAndSet(this, s, s | SIGNAL)) {
+ (s = (int)STATUS.getAndBitwiseOr(this, SIGNAL)) >= 0) {
synchronized (this) {
if (status >= 0)
wait(ms); // OK to throw InterruptedException
@@ -1046,15 +1059,13 @@
}
}
if (s >= 0)
- s = status;
- if ((s &= DONE_MASK) != NORMAL) {
- if (s == CANCELLED)
- throw new CancellationException();
- if (s != EXCEPTIONAL)
- throw new TimeoutException();
+ throw new TimeoutException();
+ else if ((s & THROWN) != 0)
throw new ExecutionException(getThrowableException());
- }
- return getRawResult();
+ else if ((s & ABNORMAL) != 0)
+ throw new CancellationException();
+ else
+ return getRawResult();
}
/**
@@ -1110,7 +1121,7 @@
* setRawResult(null)}.
*/
public void reinitialize() {
- if ((status & DONE_MASK) == EXCEPTIONAL)
+ if ((status & THROWN) != 0)
clearExceptionalCompletion();
else
status = 0;
@@ -1327,8 +1338,8 @@
*/
public final short setForkJoinTaskTag(short newValue) {
for (int s;;) {
- if (STATUS.compareAndSet(this, s = status,
- (s & ~SMASK) | (newValue & SMASK)))
+ if (STATUS.weakCompareAndSet(this, s = status,
+ (s & ~SMASK) | (newValue & SMASK)))
return (short)s;
}
}
@@ -1351,8 +1362,8 @@
for (int s;;) {
if ((short)(s = status) != expect)
return false;
- if (STATUS.compareAndSet(this, s,
- (s & ~SMASK) | (update & SMASK)))
+ if (STATUS.weakCompareAndSet(this, s,
+ (s & ~SMASK) | (update & SMASK)))
return true;
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java
--- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java Thu Dec 14 12:28:32 2017 +0000
@@ -1252,18 +1252,20 @@
head = h += taken;
d = subtractDemand(taken);
}
- else if ((empty = (t == h)) && (c & COMPLETE) != 0) {
- closeOnComplete(s); // end of stream
- break;
- }
else if ((d = demand) == 0L && (c & REQS) != 0)
weakCasCtl(c, c & ~REQS); // exhausted demand
else if (d != 0L && (c & REQS) == 0)
weakCasCtl(c, c | REQS); // new demand
- else if (t == (t = tail) && (empty || d == 0L)) {
- int bit = ((c & ACTIVE) != 0) ? ACTIVE : RUN;
- if (weakCasCtl(c, c & ~bit) && bit == RUN)
- break; // un-keep-alive or exit
+ else if (t == (t = tail)) { // stability check
+ if ((empty = (t == h)) && (c & COMPLETE) != 0) {
+ closeOnComplete(s); // end of stream
+ break;
+ }
+ else if (empty || d == 0L) {
+ int bit = ((c & ACTIVE) != 0) ? ACTIVE : RUN;
+ if (weakCasCtl(c, c & ~bit) && bit == RUN)
+ break; // un-keep-alive or exit
+ }
}
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java
--- a/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAccumulator.java Thu Dec 14 12:28:32 2017 +0000
@@ -105,20 +105,20 @@
* @param x the value
*/
public void accumulate(double x) {
- Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null
+ Cell[] cs; long b, v, r; int m; Cell c;
+ if ((cs = cells) != null
|| ((r = doubleToRawLongBits
(function.applyAsDouble(longBitsToDouble(b = base), x))) != b
&& !casBase(b, r))) {
boolean uncontended = true;
- if (as == null
- || (m = as.length - 1) < 0
- || (a = as[getProbe() & m]) == null
+ if (cs == null
+ || (m = cs.length - 1) < 0
+ || (c = cs[getProbe() & m]) == null
|| !(uncontended =
((r = doubleToRawLongBits
(function.applyAsDouble
- (longBitsToDouble(v = a.value), x))) == v)
- || a.cas(v, r)))
+ (longBitsToDouble(v = c.value), x))) == v)
+ || c.cas(v, r)))
doubleAccumulate(x, function, uncontended);
}
}
@@ -133,13 +133,13 @@
* @return the current value
*/
public double get() {
- Cell[] as = cells;
+ Cell[] cs = cells;
double result = longBitsToDouble(base);
- if (as != null) {
- for (Cell a : as)
- if (a != null)
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
result = function.applyAsDouble
- (result, longBitsToDouble(a.value));
+ (result, longBitsToDouble(c.value));
}
return result;
}
@@ -153,12 +153,12 @@
* updating.
*/
public void reset() {
- Cell[] as = cells;
+ Cell[] cs = cells;
base = identity;
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- a.reset(identity);
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ c.reset(identity);
}
}
@@ -173,14 +173,12 @@
* @return the value before reset
*/
public double getThenReset() {
- Cell[] as = cells;
- double result = longBitsToDouble(base);
- base = identity;
- if (as != null) {
- for (Cell a : as) {
- if (a != null) {
- double v = longBitsToDouble(a.value);
- a.reset(identity);
+ Cell[] cs = cells;
+ double result = longBitsToDouble(getAndSetBase(identity));
+ if (cs != null) {
+ for (Cell c : cs) {
+ if (c != null) {
+ double v = longBitsToDouble(c.getAndSet(identity));
result = function.applyAsDouble(result, v);
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java
--- a/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/DoubleAdder.java Thu Dec 14 12:28:32 2017 +0000
@@ -87,15 +87,15 @@
* @param x the value to add
*/
public void add(double x) {
- Cell[] as; long b, v; int m; Cell a;
- if ((as = cells) != null ||
+ Cell[] cs; long b, v; int m; Cell c;
+ if ((cs = cells) != null ||
!casBase(b = base,
Double.doubleToRawLongBits
(Double.longBitsToDouble(b) + x))) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended = a.cas(v = a.value,
+ if (cs == null || (m = cs.length - 1) < 0 ||
+ (c = cs[getProbe() & m]) == null ||
+ !(uncontended = c.cas(v = c.value,
Double.doubleToRawLongBits
(Double.longBitsToDouble(v) + x))))
doubleAccumulate(x, null, uncontended);
@@ -115,12 +115,12 @@
* @return the sum
*/
public double sum() {
- Cell[] as = cells;
+ Cell[] cs = cells;
double sum = Double.longBitsToDouble(base);
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- sum += Double.longBitsToDouble(a.value);
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ sum += Double.longBitsToDouble(c.value);
}
return sum;
}
@@ -133,12 +133,12 @@
* known that no threads are concurrently updating.
*/
public void reset() {
- Cell[] as = cells;
+ Cell[] cs = cells;
base = 0L; // relies on fact that double 0 must have same rep as long
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- a.reset();
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ c.reset();
}
}
@@ -153,16 +153,12 @@
* @return the sum
*/
public double sumThenReset() {
- Cell[] as = cells;
- double sum = Double.longBitsToDouble(base);
- base = 0L;
- if (as != null) {
- for (Cell a : as) {
- if (a != null) {
- long v = a.value;
- a.reset();
- sum += Double.longBitsToDouble(v);
- }
+ Cell[] cs = cells;
+ double sum = Double.longBitsToDouble(getAndSetBase(0L));
+ if (cs != null) {
+ for (Cell c : cs) {
+ if (c != null)
+ sum += Double.longBitsToDouble(c.getAndSet(0L));
}
}
return sum;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java
--- a/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java Thu Dec 14 12:28:32 2017 +0000
@@ -103,17 +103,17 @@
* @param x the value
*/
public void accumulate(long x) {
- Cell[] as; long b, v, r; int m; Cell a;
- if ((as = cells) != null
+ Cell[] cs; long b, v, r; int m; Cell c;
+ if ((cs = cells) != null
|| ((r = function.applyAsLong(b = base, x)) != b
&& !casBase(b, r))) {
boolean uncontended = true;
- if (as == null
- || (m = as.length - 1) < 0
- || (a = as[getProbe() & m]) == null
+ if (cs == null
+ || (m = cs.length - 1) < 0
+ || (c = cs[getProbe() & m]) == null
|| !(uncontended =
- (r = function.applyAsLong(v = a.value, x)) == v
- || a.cas(v, r)))
+ (r = function.applyAsLong(v = c.value, x)) == v
+ || c.cas(v, r)))
longAccumulate(x, function, uncontended);
}
}
@@ -128,12 +128,12 @@
* @return the current value
*/
public long get() {
- Cell[] as = cells;
+ Cell[] cs = cells;
long result = base;
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- result = function.applyAsLong(result, a.value);
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ result = function.applyAsLong(result, c.value);
}
return result;
}
@@ -147,12 +147,12 @@
* updating.
*/
public void reset() {
- Cell[] as = cells;
+ Cell[] cs = cells;
base = identity;
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- a.reset(identity);
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ c.reset(identity);
}
}
@@ -167,14 +167,12 @@
* @return the value before reset
*/
public long getThenReset() {
- Cell[] as = cells;
- long result = base;
- base = identity;
- if (as != null) {
- for (Cell a : as) {
- if (a != null) {
- long v = a.value;
- a.reset(identity);
+ Cell[] cs = cells;
+ long result = getAndSetBase(identity);
+ if (cs != null) {
+ for (Cell c : cs) {
+ if (c != null) {
+ long v = c.getAndSet(identity);
result = function.applyAsLong(result, v);
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java
--- a/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/LongAdder.java Thu Dec 14 12:28:32 2017 +0000
@@ -83,12 +83,12 @@
* @param x the value to add
*/
public void add(long x) {
- Cell[] as; long b, v; int m; Cell a;
- if ((as = cells) != null || !casBase(b = base, b + x)) {
+ Cell[] cs; long b, v; int m; Cell c;
+ if ((cs = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
- if (as == null || (m = as.length - 1) < 0 ||
- (a = as[getProbe() & m]) == null ||
- !(uncontended = a.cas(v = a.value, v + x)))
+ if (cs == null || (m = cs.length - 1) < 0 ||
+ (c = cs[getProbe() & m]) == null ||
+ !(uncontended = c.cas(v = c.value, v + x)))
longAccumulate(x, null, uncontended);
}
}
@@ -117,12 +117,12 @@
* @return the sum
*/
public long sum() {
- Cell[] as = cells;
+ Cell[] cs = cells;
long sum = base;
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- sum += a.value;
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ sum += c.value;
}
return sum;
}
@@ -135,12 +135,12 @@
* known that no threads are concurrently updating.
*/
public void reset() {
- Cell[] as = cells;
+ Cell[] cs = cells;
base = 0L;
- if (as != null) {
- for (Cell a : as)
- if (a != null)
- a.reset();
+ if (cs != null) {
+ for (Cell c : cs)
+ if (c != null)
+ c.reset();
}
}
@@ -155,15 +155,12 @@
* @return the sum
*/
public long sumThenReset() {
- Cell[] as = cells;
- long sum = base;
- base = 0L;
- if (as != null) {
- for (Cell a : as) {
- if (a != null) {
- sum += a.value;
- a.reset();
- }
+ Cell[] cs = cells;
+ long sum = getAndSetBase(0L);
+ if (cs != null) {
+ for (Cell c : cs) {
+ if (c != null)
+ sum += c.getAndSet(0L);
}
}
return sum;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java
--- a/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java Thu Dec 14 12:28:32 2017 +0000
@@ -133,6 +133,9 @@
final void reset(long identity) {
VALUE.setVolatile(this, identity);
}
+ final long getAndSet(long val) {
+ return (long)VALUE.getAndSet(this, val);
+ }
// VarHandle mechanics
private static final VarHandle VALUE;
@@ -178,6 +181,10 @@
return BASE.compareAndSet(this, cmp, val);
}
+ final long getAndSetBase(long val) {
+ return (long)BASE.getAndSet(this, val);
+ }
+
/**
* CASes the cellsBusy field from 0 to 1 to acquire lock.
*/
@@ -228,9 +235,9 @@
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
- Cell[] as; Cell a; int n; long v;
- if ((as = cells) != null && (n = as.length) > 0) {
- if ((a = as[(n - 1) & h]) == null) {
+ Cell[] cs; Cell c; int n; long v;
+ if ((cs = cells) != null && (n = cs.length) > 0) {
+ if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (cellsBusy == 0 && casCellsBusy()) {
@@ -252,17 +259,17 @@
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
- else if (a.cas(v = a.value,
+ else if (c.cas(v = c.value,
(fn == null) ? v + x : fn.applyAsLong(v, x)))
break;
- else if (n >= NCPU || cells != as)
+ else if (n >= NCPU || cells != cs)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
- if (cells == as) // Expand table unless stale
- cells = Arrays.copyOf(as, n << 1);
+ if (cells == cs) // Expand table unless stale
+ cells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
@@ -271,9 +278,9 @@
}
h = advanceProbe(h);
}
- else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
+ else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
- if (cells == as) {
+ if (cells == cs) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
@@ -312,9 +319,9 @@
}
boolean collide = false; // True if last slot nonempty
done: for (;;) {
- Cell[] as; Cell a; int n; long v;
- if ((as = cells) != null && (n = as.length) > 0) {
- if ((a = as[(n - 1) & h]) == null) {
+ Cell[] cs; Cell c; int n; long v;
+ if ((cs = cells) != null && (n = cs.length) > 0) {
+ if ((c = cs[(n - 1) & h]) == null) {
if (cellsBusy == 0) { // Try to attach new Cell
Cell r = new Cell(Double.doubleToRawLongBits(x));
if (cellsBusy == 0 && casCellsBusy()) {
@@ -336,16 +343,16 @@
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
- else if (a.cas(v = a.value, apply(fn, v, x)))
+ else if (c.cas(v = c.value, apply(fn, v, x)))
break;
- else if (n >= NCPU || cells != as)
+ else if (n >= NCPU || cells != cs)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (cellsBusy == 0 && casCellsBusy()) {
try {
- if (cells == as) // Expand table unless stale
- cells = Arrays.copyOf(as, n << 1);
+ if (cells == cs) // Expand table unless stale
+ cells = Arrays.copyOf(cs, n << 1);
} finally {
cellsBusy = 0;
}
@@ -354,9 +361,9 @@
}
h = advanceProbe(h);
}
- else if (cellsBusy == 0 && cells == as && casCellsBusy()) {
+ else if (cellsBusy == 0 && cells == cs && casCellsBusy()) {
try { // Initialize table
- if (cells == as) {
+ if (cells == cs) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(Double.doubleToRawLongBits(x));
cells = rs;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/jar/JarFile.java
--- a/src/java.base/share/classes/java/util/jar/JarFile.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/jar/JarFile.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -112,9 +112,9 @@
*
* {@code jdk.util.jar.version} can be assigned a value that is the
* {@code String} representation of a non-negative integer
- * {@code <= Runtime.version().major()}. The value is used to set the effective
+ * {@code <= Runtime.version().feature()}. The value is used to set the effective
* runtime version to something other than the default value obtained by
- * evaluating {@code Runtime.version().major()}. The effective runtime version
+ * evaluating {@code Runtime.version().feature()}. The effective runtime version
* is the version that the {@link JarFile#JarFile(File, boolean, int, Runtime.Version)}
* constructor uses when the value of the last argument is
* {@code JarFile.runtimeVersion()}.
@@ -143,7 +143,7 @@
public
class JarFile extends ZipFile {
private final static Runtime.Version BASE_VERSION;
- private final static int BASE_VERSION_MAJOR;
+ private final static int BASE_VERSION_FEATURE;
private final static Runtime.Version RUNTIME_VERSION;
private final static boolean MULTI_RELEASE_ENABLED;
private final static boolean MULTI_RELEASE_FORCED;
@@ -153,7 +153,7 @@
private boolean jvInitialized;
private boolean verify;
private final Runtime.Version version; // current version
- private final int versionMajor; // version.major()
+ private final int versionFeature; // version.feature()
private boolean isMultiRelease; // is jar multi-release?
// indicates if Class-Path attribute present
@@ -170,14 +170,14 @@
JUZFA = jdk.internal.misc.SharedSecrets.getJavaUtilZipFileAccess();
// multi-release jar file versions >= 9
BASE_VERSION = Runtime.Version.parse(Integer.toString(8));
- BASE_VERSION_MAJOR = BASE_VERSION.major();
+ BASE_VERSION_FEATURE = BASE_VERSION.feature();
String jarVersion = GetPropertyAction.privilegedGetProperty("jdk.util.jar.version");
- int runtimeVersion = Runtime.version().major();
+ int runtimeVersion = Runtime.version().feature();
if (jarVersion != null) {
int jarVer = Integer.parseInt(jarVersion);
runtimeVersion = (jarVer > runtimeVersion)
? runtimeVersion
- : Math.max(jarVer, BASE_VERSION_MAJOR);
+ : Math.max(jarVer, BASE_VERSION_FEATURE);
}
RUNTIME_VERSION = Runtime.Version.parse(Integer.toString(runtimeVersion));
String enableMultiRelease = GetPropertyAction
@@ -224,10 +224,10 @@
* Returns the version that represents the effective runtime versioned
* configuration of a multi-release jar file.
*
- * By default the major version number of the returned {@code Version} will
- * be equal to the major version number of {@code Runtime.version()}.
+ * By default the feature version number of the returned {@code Version} will
+ * be equal to the feature version number of {@code Runtime.version()}.
* However, if the {@code jdk.util.jar.version} property is set, the
- * returned {@code Version} is derived from that property and major version
+ * returned {@code Version} is derived from that property and feature version
* numbers may not be equal.
*
* @return the version that represents the runtime versioned configuration
@@ -322,7 +322,7 @@
*
* The canonical form derived from the version parameter is
* {@code Runtime.Version.parse(Integer.toString(n))} where {@code n} is
- * {@code Math.max(version.major(), JarFile.baseVersion().major())}.
+ * {@code Math.max(version.feature(), JarFile.baseVersion().feature())}.
*
* @param file the jar file to be opened for reading
* @param verify whether or not to verify the jar file if
@@ -341,17 +341,17 @@
super(file, mode);
this.verify = verify;
Objects.requireNonNull(version);
- if (MULTI_RELEASE_FORCED || version.major() == RUNTIME_VERSION.major()) {
+ if (MULTI_RELEASE_FORCED || version.feature() == RUNTIME_VERSION.feature()) {
// This deals with the common case where the value from JarFile.runtimeVersion() is passed
this.version = RUNTIME_VERSION;
- } else if (version.major() <= BASE_VERSION_MAJOR) {
+ } else if (version.feature() <= BASE_VERSION_FEATURE) {
// This also deals with the common case where the value from JarFile.baseVersion() is passed
this.version = BASE_VERSION;
} else {
// Canonicalize
- this.version = Runtime.Version.parse(Integer.toString(version.major()));
+ this.version = Runtime.Version.parse(Integer.toString(version.feature()));
}
- this.versionMajor = this.version.major();
+ this.versionFeature = this.version.feature();
}
/**
@@ -579,7 +579,7 @@
// filter out dir META-INF/versions/ and META-INF/versions/*/
// and any entry with version > 'version'
if (index == -1 || index == (name.length() - 1) ||
- Integer.parseInt(name, off, index, 10) > versionMajor) {
+ Integer.parseInt(name, off, index, 10) > versionFeature) {
return null;
}
} catch (NumberFormatException x) {
@@ -592,11 +592,11 @@
}
private JarEntry getVersionedEntry(String name, JarEntry je) {
- if (BASE_VERSION_MAJOR < versionMajor) {
+ if (BASE_VERSION_FEATURE < versionFeature) {
if (!name.startsWith(META_INF)) {
// search for versioned entry
- int v = versionMajor;
- while (v > BASE_VERSION_MAJOR) {
+ int v = versionFeature;
+ while (v > BASE_VERSION_FEATURE) {
JarFileEntry vje = getEntry0(META_INF_VERSIONS + v + "/" + name);
if (vje != null) {
return vje.withBasename(name);
@@ -673,7 +673,7 @@
}
JarFileEntry realEntry() {
- if (isMultiRelease() && versionMajor != BASE_VERSION_MAJOR) {
+ if (isMultiRelease() && versionFeature != BASE_VERSION_FEATURE) {
String entryName = super.getName();
return entryName == basename || entryName.equals(basename) ?
this : new JarFileEntry(entryName, this);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/spi/LocaleNameProvider.java
--- a/src/java.base/share/classes/java/util/spi/LocaleNameProvider.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/spi/LocaleNameProvider.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* 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 java.util.spi;
import java.util.Locale;
+import java.util.Objects;
/**
* An abstract class for service providers that
@@ -141,4 +142,54 @@
* @see java.util.Locale#getDisplayVariant(java.util.Locale)
*/
public abstract String getDisplayVariant(String variant, Locale locale);
+
+ /**
+ * Returns a localized name for the given
+ * Unicode extension key,
+ * and the given locale that is appropriate for display to the user.
+ * If the name returned cannot be localized according to {@code locale},
+ * this method returns null.
+ * @implSpec the default implementation returns {@code null}.
+ * @param key the Unicode Extension key, not null.
+ * @param locale the desired locale, not null.
+ * @return the name of the given key string for the specified locale,
+ * or null if it's not available.
+ * @exception NullPointerException if {@code key} or {@code locale} is null
+ * @exception IllegalArgumentException if {@code locale} isn't
+ * one of the locales returned from
+ * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
+ * getAvailableLocales()}.
+ * @since 10
+ */
+ public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(locale);
+ return null;
+ }
+
+ /**
+ * Returns a localized name for the given
+ * Unicode extension type,
+ * and the given locale that is appropriate for display to the user.
+ * If the name returned cannot be localized according to {@code locale},
+ * this method returns null.
+ * @implSpec the default implementation returns {@code null}.
+ * @param type the Unicode Extension type, not null.
+ * @param key the Unicode Extension key for this {@code type}, not null.
+ * @param locale the desired locale, not null.
+ * @return the name of the given type string for the specified locale,
+ * or null if it's not available.
+ * @exception NullPointerException if {@code key}, {@code type} or {@code locale} is null
+ * @exception IllegalArgumentException if {@code locale} isn't
+ * one of the locales returned from
+ * {@link java.util.spi.LocaleServiceProvider#getAvailableLocales()
+ * getAvailableLocales()}.
+ * @since 10
+ */
+ public String getDisplayUnicodeExtensionType(String type, String key, Locale locale) {
+ Objects.requireNonNull(type);
+ Objects.requireNonNull(key);
+ Objects.requireNonNull(locale);
+ return null;
+ }
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/zip/Deflater.java
--- a/src/java.base/share/classes/java/util/zip/Deflater.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/zip/Deflater.java Thu Dec 14 12:28:32 2017 +0000
@@ -67,12 +67,26 @@
* }
*
*
+ * @apiNote
+ * To release resources used by this {@code Deflater}, the {@link #end()} method
+ * should be called explicitly. Subclasses are responsible for the cleanup of resources
+ * acquired by the subclass. Subclasses that override {@link #finalize()} in order
+ * to perform cleanup should be modified to use alternative cleanup mechanisms such
+ * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
+ *
+ * @implSpec
+ * If this {@code Deflater} has been subclassed and the {@code end} method has been
+ * overridden, the {@code end} method will be called by the finalization when the
+ * deflater is unreachable. But the subclasses should not depend on this specific
+ * implementation; the finalization is not reliable and the {@code finalize} method
+ * is deprecated to be removed.
+ *
* @see Inflater
* @author David Connelly
* @since 1.1
*/
-public
-class Deflater {
+
+public class Deflater {
private final ZStreamRef zsRef;
private byte[] buf = new byte[0];
@@ -169,7 +183,9 @@
public Deflater(int level, boolean nowrap) {
this.level = level;
this.strategy = DEFAULT_STRATEGY;
- this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
+ this.zsRef = ZStreamRef.get(this,
+ () -> init(level, DEFAULT_STRATEGY, nowrap),
+ Deflater::end);
}
/**
@@ -534,38 +550,32 @@
/**
* Closes the compressor and discards any unprocessed input.
+ *
* This method should be called when the compressor is no longer
- * being used, but will also be called automatically by the
- * finalize() method. Once this method is called, the behavior
- * of the Deflater object is undefined.
+ * being used. Once this method is called, the behavior of the
+ * Deflater object is undefined.
*/
public void end() {
synchronized (zsRef) {
- long addr = zsRef.address();
- zsRef.clear();
- if (addr != 0) {
- end(addr);
- buf = null;
- }
+ zsRef.clean();
+ buf = null;
}
}
/**
* Closes the compressor when garbage is collected.
*
- * @deprecated The {@code finalize} method has been deprecated.
- * Subclasses that override {@code finalize} in order to perform cleanup
- * should be modified to use alternative cleanup mechanisms and
- * to remove the overriding {@code finalize} method.
- * When overriding the {@code finalize} method, its implementation must explicitly
- * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
- * See the specification for {@link Object#finalize()} for further
- * information about migration options.
+ * @deprecated The {@code finalize} method has been deprecated and will be
+ * removed. It is implemented as a no-op. Subclasses that override
+ * {@code finalize} in order to perform cleanup should be modified to use
+ * alternative cleanup mechanisms and to remove the overriding {@code finalize}
+ * method. The recommended cleanup for compressor is to explicitly call
+ * {@code end} method when it is no longer in use. If the {@code end} is
+ * not invoked explicitly the resource of the compressor will be released
+ * when the instance becomes unreachable.
*/
- @Deprecated(since="9")
- protected void finalize() {
- end();
- }
+ @Deprecated(since="9", forRemoval=true)
+ protected void finalize() {}
private void ensureOpen() {
assert Thread.holdsLock(zsRef);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/zip/Inflater.java
--- a/src/java.base/share/classes/java/util/zip/Inflater.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/zip/Inflater.java Thu Dec 14 12:28:32 2017 +0000
@@ -66,13 +66,27 @@
* }
*
*
+ * @apiNote
+ * To release resources used by this {@code Inflater}, the {@link #end()} method
+ * should be called explicitly. Subclasses are responsible for the cleanup of resources
+ * acquired by the subclass. Subclasses that override {@link #finalize()} in order
+ * to perform cleanup should be modified to use alternative cleanup mechanisms such
+ * as {@link java.lang.ref.Cleaner} and remove the overriding {@code finalize} method.
+ *
+ * @implSpec
+ * If this {@code Inflater} has been subclassed and the {@code end} method has been
+ * overridden, the {@code end} method will be called by the finalization when the
+ * inflater is unreachable. But the subclasses should not depend on this specific
+ * implementation; the finalization is not reliable and the {@code finalize} method
+ * is deprecated to be removed.
+ *
* @see Deflater
* @author David Connelly
* @since 1.1
*
*/
-public
-class Inflater {
+
+public class Inflater {
private final ZStreamRef zsRef;
private byte[] buf = defaultBuf;
@@ -101,7 +115,7 @@
* @param nowrap if true then support GZIP compatible compression
*/
public Inflater(boolean nowrap) {
- zsRef = new ZStreamRef(init(nowrap));
+ this.zsRef = ZStreamRef.get(this, () -> init(nowrap), Inflater::end);
}
/**
@@ -361,38 +375,37 @@
/**
* Closes the decompressor and discards any unprocessed input.
+ *
* This method should be called when the decompressor is no longer
- * being used, but will also be called automatically by the finalize()
- * method. Once this method is called, the behavior of the Inflater
- * object is undefined.
+ * being used. Once this method is called, the behavior of the
+ * Inflater object is undefined.
*/
public void end() {
synchronized (zsRef) {
- long addr = zsRef.address();
- zsRef.clear();
- if (addr != 0) {
- end(addr);
- buf = null;
- }
+ zsRef.clean();
+ buf = null;
}
}
/**
* Closes the decompressor when garbage is collected.
*
- * @deprecated The {@code finalize} method has been deprecated.
- * Subclasses that override {@code finalize} in order to perform cleanup
- * should be modified to use alternative cleanup mechanisms and
- * to remove the overriding {@code finalize} method.
- * When overriding the {@code finalize} method, its implementation must explicitly
- * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
- * See the specification for {@link Object#finalize()} for further
- * information about migration options.
+ * @implSpec
+ * If this {@code Inflater} has been subclassed and the {@code end} method
+ * has been overridden, the {@code end} method will be called when the
+ * inflater is unreachable.
+ *
+ * @deprecated The {@code finalize} method has been deprecated and will be
+ * removed. It is implemented as a no-op. Subclasses that override
+ * {@code finalize} in order to perform cleanup should be modified to use
+ * alternative cleanup mechanisms and remove the overriding {@code finalize}
+ * method. The recommended cleanup for compressor is to explicitly call
+ * {@code end} method when it is no longer in use. If the {@code end} is
+ * not invoked explicitly the resource of the compressor will be released
+ * when the instance becomes unreachable,
*/
- @Deprecated(since="9")
- protected void finalize() {
- end();
- }
+ @Deprecated(since="9", forRemoval=true)
+ protected void finalize() {}
private void ensureOpen () {
assert Thread.holdsLock(zsRef);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/zip/ZStreamRef.java
--- a/src/java.base/share/classes/java/util/zip/ZStreamRef.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/zip/ZStreamRef.java Thu Dec 14 12:28:32 2017 +0000
@@ -25,22 +25,89 @@
package java.util.zip;
-/**
- * A reference to the native zlib's z_stream structure.
- */
+import java.util.function.LongConsumer;
+import java.util.function.LongSupplier;
+import java.lang.ref.Cleaner.Cleanable;
+import jdk.internal.ref.CleanerFactory;
-class ZStreamRef {
+/**
+ * A reference to the native zlib's z_stream structure. It also
+ * serves as the "cleaner" to clean up the native resource when
+ * the deflater or infalter is ended, closed or cleaned.
+ */
+class ZStreamRef implements Runnable {
- private volatile long address;
- ZStreamRef (long address) {
- this.address = address;
+ private LongConsumer end;
+ private long address;
+ private final Cleanable cleanable;
+
+ private ZStreamRef (Object owner, LongSupplier addr, LongConsumer end) {
+ this.cleanable = CleanerFactory.cleaner().register(owner, this);
+ this.end = end;
+ this.address = addr.getAsLong();
}
long address() {
return address;
}
- void clear() {
+ void clean() {
+ cleanable.clean();
+ }
+
+ public synchronized void run() {
+ long addr = address;
address = 0;
+ if (addr != 0) {
+ end.accept(addr);
+ }
+ }
+
+ private ZStreamRef (LongSupplier addr, LongConsumer end) {
+ this.cleanable = null;
+ this.end = end;
+ this.address = addr.getAsLong();
+ }
+
+ /*
+ * If {@code Inflater/Deflater} has been subclassed and the {@code end} method
+ * is overridden, uses {@code finalizer} mechanism for resource cleanup. So
+ * {@code end} method can be called when the {@code Inflater/Deflater} is
+ * unreachable. This mechanism will be removed when the {@code finalize} method
+ * is removed from {@code Inflater/Deflater}.
+ */
+ static ZStreamRef get(Object owner, LongSupplier addr, LongConsumer end) {
+ Class> clz = owner.getClass();
+ while (clz != Deflater.class && clz != Inflater.class) {
+ try {
+ clz.getDeclaredMethod("end");
+ return new FinalizableZStreamRef(owner, addr, end);
+ } catch (NoSuchMethodException nsme) {}
+ clz = clz.getSuperclass();
+ }
+ return new ZStreamRef(owner, addr, end);
+ }
+
+ private static class FinalizableZStreamRef extends ZStreamRef {
+ final Object owner;
+
+ FinalizableZStreamRef (Object owner, LongSupplier addr, LongConsumer end) {
+ super(addr, end);
+ this.owner = owner;
+ }
+
+ @Override
+ void clean() {
+ run();
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected void finalize() {
+ if (owner instanceof Inflater)
+ ((Inflater)owner).end();
+ else
+ ((Deflater)owner).end();
+ }
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/zip/ZipCoder.java
--- a/src/java.base/share/classes/java/util/zip/ZipCoder.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/zip/ZipCoder.java Thu Dec 14 12:28:32 2017 +0000
@@ -28,72 +28,60 @@
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
-import java.nio.charset.StandardCharsets;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
-import java.nio.charset.CoderResult;
+import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
-import java.util.Arrays;
-import sun.nio.cs.ArrayDecoder;
-import sun.nio.cs.ArrayEncoder;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
/**
* Utility class for zipfile name and comment decoding and encoding
*/
-final class ZipCoder {
+class ZipCoder {
+
+ private static final jdk.internal.misc.JavaLangAccess JLA =
+ jdk.internal.misc.SharedSecrets.getJavaLangAccess();
+
+ static final class UTF8 extends ZipCoder {
+
+ UTF8(Charset utf8) {
+ super(utf8);
+ }
- private static boolean isASCII(byte[] ba, int off, int len) {
- for (int i = off; i < off + len; i++) {
- if (ba[i] < 0)
- return false;
+ @Override
+ boolean isUTF8() {
+ return true;
}
- return true;
+
+ @Override
+ String toString(byte[] ba, int off, int length) {
+ return JLA.newStringUTF8NoRepl(ba, off, length);
+ }
+
+ @Override
+ byte[] getBytes(String s) {
+ return JLA.getBytesUTF8NoRepl(s);
+ }
}
- private static boolean hasReplaceChar(byte[] ba) {
- for (int i = 0; i < ba.length; i++) {
- if (ba[i] == (byte)'?')
- return true;
- }
- return false;
+ // UTF_8.ArrayEn/Decoder is stateless, so make it singleton.
+ private static ZipCoder utf8 = new UTF8(UTF_8);
+
+ public static ZipCoder get(Charset charset) {
+ if (charset == UTF_8)
+ return utf8;
+ return new ZipCoder(charset);
}
String toString(byte[] ba, int off, int length) {
-
- // fastpath for UTF-8 cs and ascii only name, leverage the
- // compact string impl to avoid the unnecessary char[] copy/
- // paste. A temporary workaround before we have better approach,
- // such as a String constructor that throws exception for
- // malformed and/or unmappable characters, instead of silently
- // replacing with repl char
- if (isUTF8 && isASCII(ba, off, length)) {
- return new String(ba, off, length, cs);
- }
+ try {
+ return decoder().decode(ByteBuffer.wrap(ba, off, length)).toString();
- CharsetDecoder cd = decoder().reset();
- int len = (int)(length * cd.maxCharsPerByte());
- char[] ca = new char[len];
- if (len == 0)
- return new String(ca);
- // UTF-8 only for now. Other ArrayDeocder only handles
- // CodingErrorAction.REPLACE mode. ZipCoder uses
- // REPORT mode.
- if (isUTF8 && cd instanceof ArrayDecoder) {
- int clen = ((ArrayDecoder)cd).decode(ba, off, length, ca);
- if (clen == -1) // malformed
- throw new IllegalArgumentException("MALFORMED");
- return new String(ca, 0, clen);
+ } catch (CharacterCodingException x) {
+ throw new IllegalArgumentException(x);
}
- ByteBuffer bb = ByteBuffer.wrap(ba, off, length);
- CharBuffer cb = CharBuffer.wrap(ca);
- CoderResult cr = cd.decode(bb, cb, true);
- if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
- cr = cd.flush(cb);
- if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
- return new String(ca, 0, cb.position());
}
String toString(byte[] ba, int length) {
@@ -105,84 +93,47 @@
}
byte[] getBytes(String s) {
- if (isUTF8) {
- // fastpath for UTF8. should only occur when the string
- // has malformed surrogates. A postscan should still be
- // faster and use less memory.
- byte[] ba = s.getBytes(cs);
- if (!hasReplaceChar(ba)) {
- return ba;
+ try {
+ ByteBuffer bb = encoder().encode(CharBuffer.wrap(s));
+ int pos = bb.position();
+ int limit = bb.limit();
+ if (bb.hasArray() && pos == 0 && limit == bb.capacity()) {
+ return bb.array();
}
+ byte[] bytes = new byte[bb.limit() - bb.position()];
+ bb.get(bytes);
+ return bytes;
+ } catch (CharacterCodingException x) {
+ throw new IllegalArgumentException(x);
}
- CharsetEncoder ce = encoder().reset();
- char[] ca = s.toCharArray();
- int len = (int)(ca.length * ce.maxBytesPerChar());
- byte[] ba = new byte[len];
- if (len == 0)
- return ba;
- // UTF-8 only for now. Other ArrayDeocder only handles
- // CodingErrorAction.REPLACE mode.
- if (isUTF8 && ce instanceof ArrayEncoder) {
- int blen = ((ArrayEncoder)ce).encode(ca, 0, ca.length, ba);
- if (blen == -1) // malformed
- throw new IllegalArgumentException("MALFORMED");
- return Arrays.copyOf(ba, blen);
- }
- ByteBuffer bb = ByteBuffer.wrap(ba);
- CharBuffer cb = CharBuffer.wrap(ca);
- CoderResult cr = ce.encode(cb, bb, true);
- if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
- cr = ce.flush(bb);
- if (!cr.isUnderflow())
- throw new IllegalArgumentException(cr.toString());
- if (bb.position() == ba.length) // defensive copy?
- return ba;
- else
- return Arrays.copyOf(ba, bb.position());
}
// assume invoked only if "this" is not utf8
byte[] getBytesUTF8(String s) {
- if (isUTF8)
- return getBytes(s);
- if (utf8 == null)
- utf8 = new ZipCoder(StandardCharsets.UTF_8);
return utf8.getBytes(s);
}
String toStringUTF8(byte[] ba, int len) {
- return toStringUTF8(ba, 0, len);
+ return utf8.toString(ba, 0, len);
}
String toStringUTF8(byte[] ba, int off, int len) {
- if (isUTF8)
- return toString(ba, off, len);
- if (utf8 == null)
- utf8 = new ZipCoder(StandardCharsets.UTF_8);
return utf8.toString(ba, off, len);
}
boolean isUTF8() {
- return isUTF8;
+ return false;
}
private Charset cs;
private CharsetDecoder dec;
private CharsetEncoder enc;
- private boolean isUTF8;
- private ZipCoder utf8;
private ZipCoder(Charset cs) {
this.cs = cs;
- this.isUTF8 = cs.name().equals(StandardCharsets.UTF_8.name());
}
- static ZipCoder get(Charset charset) {
- return new ZipCoder(charset);
- }
-
- private CharsetDecoder decoder() {
+ protected CharsetDecoder decoder() {
if (dec == null) {
dec = cs.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
@@ -191,7 +142,7 @@
return dec;
}
- private CharsetEncoder encoder() {
+ protected CharsetEncoder encoder() {
if (enc == null) {
enc = cs.newEncoder()
.onMalformedInput(CodingErrorAction.REPORT)
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/java/util/zip/ZipFile.java
--- a/src/java.base/share/classes/java/util/zip/ZipFile.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/java/util/zip/ZipFile.java Thu Dec 14 12:28:32 2017 +0000
@@ -31,22 +31,24 @@
import java.io.EOFException;
import java.io.File;
import java.io.RandomAccessFile;
+import java.io.UncheckedIOException;
+import java.lang.ref.Cleaner.Cleanable;
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.Collections;
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.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.WeakHashMap;
@@ -61,8 +63,8 @@
import jdk.internal.misc.SharedSecrets;
import jdk.internal.misc.VM;
import jdk.internal.perf.PerfCounter;
+import jdk.internal.ref.CleanerFactory;
-import static java.util.zip.ZipConstants.*;
import static java.util.zip.ZipConstants64.*;
import static java.util.zip.ZipUtils.*;
@@ -73,6 +75,21 @@
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
*
+ * @apiNote
+ * To release resources used by this {@code ZipFile}, the {@link #close()} method
+ * should be called explicitly or by try-with-resources. Subclasses are responsible
+ * for the cleanup of resources acquired by the subclass. Subclasses that override
+ * {@link #finalize()} in order to perform cleanup should be modified to use alternative
+ * cleanup mechanisms such as {@link java.lang.ref.Cleaner} and remove the overriding
+ * {@code finalize} method.
+ *
+ * @implSpec
+ * If this {@code ZipFile} has been subclassed and the {@code close} method has
+ * been overridden, the {@code close} method will be called by the finalization
+ * when {@code ZipFile} is unreachable. But the subclasses should not depend on
+ * this specific implementation; the finalization is not reliable and the
+ * {@code finalize} method is deprecated to be removed.
+ *
* @author David Connelly
* @since 1.1
*/
@@ -81,9 +98,15 @@
private final String name; // zip file name
private volatile boolean closeRequested;
- private Source zsrc;
private ZipCoder zc;
+ // The "resource" used by this zip file that needs to be
+ // cleaned after use.
+ // a) the input streams that need to be closed
+ // b) the list of cached Inflater objects
+ // c) the "native" source of this zip file.
+ private final CleanableResource res;
+
private static final int STORED = ZipEntry.STORED;
private static final int DEFLATED = ZipEntry.DEFLATED;
@@ -214,10 +237,13 @@
}
}
Objects.requireNonNull(charset, "charset");
+
this.zc = ZipCoder.get(charset);
this.name = name;
long t0 = System.nanoTime();
- this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
+
+ this.res = CleanableResource.get(this, file, mode);
+
PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
PerfCounter.getZipFileCount().increment();
}
@@ -284,10 +310,10 @@
public String getComment() {
synchronized (this) {
ensureOpen();
- if (zsrc.comment == null) {
+ if (res.zsrc.comment == null) {
return null;
}
- return zc.toString(zsrc.comment);
+ return zc.toString(res.zsrc.comment);
}
}
@@ -318,7 +344,7 @@
synchronized (this) {
ensureOpen();
byte[] bname = zc.getBytes(name);
- int pos = zsrc.getEntryPos(bname, true);
+ int pos = res.zsrc.getEntryPos(bname, true);
if (pos != -1) {
return getZipEntry(name, bname, pos, func);
}
@@ -326,10 +352,6 @@
return null;
}
- // The outstanding inputstreams that need to be closed,
- // mapped to the inflater objects they use.
- private final Map streams = new WeakHashMap<>();
-
/**
* Returns an input stream for reading the contents of the specified
* zip file entry.
@@ -348,6 +370,8 @@
Objects.requireNonNull(entry, "entry");
int pos = -1;
ZipFileInputStream in = null;
+ Source zsrc = res.zsrc;
+ Set istreams = res.istreams;
synchronized (this) {
ensureOpen();
if (Objects.equals(lastEntryName, entry.name)) {
@@ -363,8 +387,8 @@
in = new ZipFileInputStream(zsrc.cen, pos);
switch (CENHOW(zsrc.cen, pos)) {
case STORED:
- synchronized (streams) {
- streams.put(in, null);
+ synchronized (istreams) {
+ istreams.add(in);
}
return in;
case DEFLATED:
@@ -377,10 +401,9 @@
if (size <= 0) {
size = 4096;
}
- Inflater inf = getInflater();
- InputStream is = new ZipFileInflaterInputStream(in, inf, (int)size);
- synchronized (streams) {
- streams.put(is, inf);
+ InputStream is = new ZipFileInflaterInputStream(in, res, (int)size);
+ synchronized (istreams) {
+ istreams.add(is);
}
return is;
default:
@@ -392,25 +415,30 @@
private class ZipFileInflaterInputStream extends InflaterInputStream {
private volatile boolean closeRequested;
private boolean eof = false;
+ private final Cleanable cleanable;
- ZipFileInflaterInputStream(ZipFileInputStream zfin, Inflater inf,
- int size) {
+ ZipFileInflaterInputStream(ZipFileInputStream zfin,
+ CleanableResource res, int size) {
+ this(zfin, res, res.getInflater(), size);
+ }
+
+ private ZipFileInflaterInputStream(ZipFileInputStream zfin,
+ CleanableResource res,
+ Inflater inf, int size) {
super(zfin, inf, size);
- }
+ this.cleanable = CleanerFactory.cleaner().register(this,
+ () -> res.releaseInflater(inf));
+ }
public void close() throws IOException {
if (closeRequested)
return;
closeRequested = true;
-
super.close();
- Inflater inf;
- synchronized (streams) {
- inf = streams.remove(this);
+ synchronized (res.istreams) {
+ res.istreams.remove(this);
}
- if (inf != null) {
- releaseInflater(inf);
- }
+ cleanable.clean();
}
// Override fill() method to provide an extra "dummy" byte
@@ -436,44 +464,8 @@
return (avail > (long) Integer.MAX_VALUE ?
Integer.MAX_VALUE : (int) avail);
}
-
- @SuppressWarnings("deprecation")
- protected void finalize() throws Throwable {
- close();
- }
}
- /*
- * Gets an inflater from the list of available inflaters or allocates
- * a new one.
- */
- private Inflater getInflater() {
- Inflater inf;
- synchronized (inflaterCache) {
- while ((inf = inflaterCache.poll()) != null) {
- if (!inf.ended()) {
- return inf;
- }
- }
- }
- return new Inflater(true);
- }
-
- /*
- * Releases the specified inflater to the list of available inflaters.
- */
- private void releaseInflater(Inflater inf) {
- if (!inf.ended()) {
- inf.reset();
- synchronized (inflaterCache) {
- inflaterCache.add(inf);
- }
- }
- }
-
- // List of available Inflater objects for decompression
- private final Deque inflaterCache = new ArrayDeque<>();
-
/**
* Returns the path name of the ZIP file.
* @return the path name of the ZIP file
@@ -518,7 +510,7 @@
throw new NoSuchElementException();
}
// each "entry" has 3 ints in table entries
- return (T)getZipEntry(null, null, zsrc.getEntryPos(i++ * 3), gen);
+ return (T)getZipEntry(null, null, res.zsrc.getEntryPos(i++ * 3), gen);
}
}
@@ -536,14 +528,14 @@
public Enumeration extends ZipEntry> entries() {
synchronized (this) {
ensureOpen();
- return new ZipEntryIterator(zsrc.total, ZipEntry::new);
+ return new ZipEntryIterator(res.zsrc.total, ZipEntry::new);
}
}
private Enumeration entries(Function func) {
synchronized (this) {
ensureOpen();
- return new ZipEntryIterator(zsrc.total, func);
+ return new ZipEntryIterator(res.zsrc.total, func);
}
}
@@ -568,7 +560,7 @@
if (index >= 0 && index < fence) {
synchronized (ZipFile.this) {
ensureOpen();
- action.accept(gen.apply(zsrc.getEntryPos(index++ * 3)));
+ action.accept(gen.apply(res.zsrc.getEntryPos(index++ * 3)));
}
return true;
}
@@ -589,13 +581,13 @@
public Stream extends ZipEntry> stream() {
synchronized (this) {
ensureOpen();
- return StreamSupport.stream(new EntrySpliterator<>(0, zsrc.total,
+ return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
pos -> getZipEntry(null, null, pos, ZipEntry::new)), false);
}
}
private String getEntryName(int pos) {
- byte[] cen = zsrc.cen;
+ byte[] cen = res.zsrc.cen;
int nlen = CENNAM(cen, pos);
int clen = CENCOM(cen, pos);
int flag = CENFLG(cen, pos);
@@ -620,7 +612,7 @@
synchronized (this) {
ensureOpen();
return StreamSupport.stream(
- new EntrySpliterator<>(0, zsrc.total, this::getEntryName), false);
+ new EntrySpliterator<>(0, res.zsrc.total, this::getEntryName), false);
}
}
@@ -638,7 +630,7 @@
private Stream stream(Function func) {
synchronized (this) {
ensureOpen();
- return StreamSupport.stream(new EntrySpliterator<>(0, zsrc.total,
+ return StreamSupport.stream(new EntrySpliterator<>(0, res.zsrc.total,
pos -> (JarEntry)getZipEntry(null, null, pos, func)), false);
}
}
@@ -649,7 +641,7 @@
/* Checks ensureOpen() before invoke this method */
private ZipEntry getZipEntry(String name, byte[] bname, int pos,
Function func) {
- byte[] cen = zsrc.cen;
+ byte[] cen = res.zsrc.cen;
int nlen = CENNAM(cen, pos);
int elen = CENEXT(cen, pos);
int clen = CENCOM(cen, pos);
@@ -698,12 +690,170 @@
public int size() {
synchronized (this) {
ensureOpen();
- return zsrc.total;
+ return res.zsrc.total;
+ }
+ }
+
+ private static class CleanableResource implements Runnable {
+ // The outstanding inputstreams that need to be closed
+ final Set istreams;
+
+ // List of cached Inflater objects for decompression
+ Deque inflaterCache;
+
+ final Cleanable cleanable;
+
+ Source zsrc;
+
+ CleanableResource(ZipFile zf, File file, int mode) throws IOException {
+ this.cleanable = CleanerFactory.cleaner().register(zf, this);
+ this.istreams = Collections.newSetFromMap(new WeakHashMap<>());
+ this.inflaterCache = new ArrayDeque<>();
+ this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
+ }
+
+ void clean() {
+ cleanable.clean();
+ }
+
+ /*
+ * Gets an inflater from the list of available inflaters or allocates
+ * a new one.
+ */
+ Inflater getInflater() {
+ Inflater inf;
+ synchronized (inflaterCache) {
+ if ((inf = inflaterCache.poll()) != null) {
+ return inf;
+ }
+ }
+ return new Inflater(true);
+ }
+
+ /*
+ * Releases the specified inflater to the list of available inflaters.
+ */
+ void releaseInflater(Inflater inf) {
+ Deque inflaters = this.inflaterCache;
+ if (inflaters != null) {
+ synchronized (inflaters) {
+ // double checked!
+ if (inflaters == this.inflaterCache) {
+ inf.reset();
+ inflaters.add(inf);
+ return;
+ }
+ }
+ }
+ // inflaters cache already closed - just end it.
+ inf.end();
+ }
+
+ public void run() {
+ IOException ioe = null;
+
+ // Release cached inflaters and close the cache first
+ Deque inflaters = this.inflaterCache;
+ if (inflaters != null) {
+ synchronized (inflaters) {
+ // no need to double-check as only one thread gets a
+ // chance to execute run() (Cleaner guarantee)...
+ Inflater inf;
+ while ((inf = inflaters.poll()) != null) {
+ inf.end();
+ }
+ // close inflaters cache
+ this.inflaterCache = null;
+ }
+ }
+
+ // Close streams, release their inflaters
+ if (istreams != null) {
+ synchronized (istreams) {
+ if (!istreams.isEmpty()) {
+ InputStream[] copy = istreams.toArray(new InputStream[0]);
+ istreams.clear();
+ for (InputStream is : copy) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ if (ioe == null) ioe = e;
+ else ioe.addSuppressed(e);
+ }
+ }
+ }
+ }
+ }
+
+ // Release zip src
+ if (zsrc != null) {
+ synchronized (zsrc) {
+ try {
+ Source.release(zsrc);
+ zsrc = null;
+ } catch (IOException e) {
+ if (ioe == null) ioe = e;
+ else ioe.addSuppressed(e);
+ }
+ }
+ }
+ if (ioe != null) {
+ throw new UncheckedIOException(ioe);
+ }
+ }
+
+ CleanableResource(File file, int mode)
+ throws IOException {
+ this.cleanable = null;
+ this.istreams = Collections.newSetFromMap(new WeakHashMap<>());
+ this.inflaterCache = new ArrayDeque<>();
+ this.zsrc = Source.get(file, (mode & OPEN_DELETE) != 0);
+ }
+
+ /*
+ * If {@code ZipFile} has been subclassed and the {@code close} method is
+ * overridden, uses the {@code finalizer} mechanism for resource cleanup.
+ * So {@code close} method can be called when the the {@code ZipFile} is
+ * unreachable. This mechanism will be removed when {@code finalize} method
+ * is removed from {@code ZipFile}.
+ */
+ static CleanableResource get(ZipFile zf, File file, int mode)
+ throws IOException {
+ Class> clz = zf.getClass();
+ while (clz != ZipFile.class) {
+ try {
+ clz.getDeclaredMethod("close");
+ return new FinalizableResource(zf, file, mode);
+ } catch (NoSuchMethodException nsme) {}
+ clz = clz.getSuperclass();
+ }
+ return new CleanableResource(zf, file, mode);
+ }
+
+ static class FinalizableResource extends CleanableResource {
+ ZipFile zf;
+ FinalizableResource(ZipFile zf, File file, int mode)
+ throws IOException {
+ super(file, mode);
+ this.zf = zf;
+ }
+
+ @Override
+ void clean() {
+ run();
+ }
+
+ @Override
+ @SuppressWarnings("deprecation")
+ protected void finalize() throws IOException {
+ zf.close();
+ }
}
}
/**
* Closes the ZIP file.
+ *
*
Closing this ZIP file will close all of the input streams
* previously returned by invocations of the {@link #getInputStream
* getInputStream} method.
@@ -717,31 +867,12 @@
closeRequested = true;
synchronized (this) {
- // Close streams, release their inflaters
- synchronized (streams) {
- if (!streams.isEmpty()) {
- Map copy = new HashMap<>(streams);
- streams.clear();
- for (Map.Entry e : copy.entrySet()) {
- e.getKey().close();
- Inflater inf = e.getValue();
- if (inf != null) {
- inf.end();
- }
- }
- }
- }
- // Release cached inflaters
- synchronized (inflaterCache) {
- Inflater inf;
- while ((inf = inflaterCache.poll()) != null) {
- inf.end();
- }
- }
- // Release zip src
- if (zsrc != null) {
- Source.close(zsrc);
- zsrc = null;
+ // Close streams, release their inflaters, release cached inflaters
+ // and release zip source
+ try {
+ res.clean();
+ } catch (UncheckedIOException ioe) {
+ throw ioe.getCause();
}
}
}
@@ -750,34 +881,26 @@
* Ensures that the system resources held by this ZipFile object are
* released when there are no more references to it.
*
- *
- * Since the time when GC would invoke this method is undetermined,
- * it is strongly recommended that applications invoke the {@code close}
- * method as soon they have finished accessing this {@code ZipFile}.
- * This will prevent holding up system resources for an undetermined
- * length of time.
+ * @deprecated The {@code finalize} method has been deprecated and will be
+ * removed. It is implemented as a no-op. Subclasses that override
+ * {@code finalize} in order to perform cleanup should be modified to
+ * use alternative cleanup mechanisms and to remove the overriding
+ * {@code finalize} method. The recommended cleanup for ZipFile object
+ * is to explicitly invoke {@code close} method when it is no longer in
+ * use, or use try-with-resources. If the {@code close} is not invoked
+ * explicitly the resources held by this object will be released when
+ * the instance becomes unreachable.
*
- * @deprecated The {@code finalize} method has been deprecated.
- * Subclasses that override {@code finalize} in order to perform cleanup
- * should be modified to use alternative cleanup mechanisms and
- * to remove the overriding {@code finalize} method.
- * When overriding the {@code finalize} method, its implementation must explicitly
- * ensure that {@code super.finalize()} is invoked as described in {@link Object#finalize}.
- * See the specification for {@link Object#finalize()} for further
- * information about migration options.
* @throws IOException if an I/O error has occurred
- * @see java.util.zip.ZipFile#close()
*/
- @Deprecated(since="9")
- protected void finalize() throws IOException {
- close();
- }
+ @Deprecated(since="9", forRemoval=true)
+ protected void finalize() throws IOException {}
private void ensureOpen() {
if (closeRequested) {
throw new IllegalStateException("zip file closed");
}
- if (zsrc == null) {
+ if (res.zsrc == null) {
throw new IllegalStateException("The object is not initialized.");
}
}
@@ -798,7 +921,7 @@
protected long rem; // number of remaining bytes within entry
protected long size; // uncompressed size of this entry
- ZipFileInputStream(byte[] cen, int cenpos) throws IOException {
+ ZipFileInputStream(byte[] cen, int cenpos) {
rem = CENSIZ(cen, cenpos);
size = CENLEN(cen, cenpos);
pos = CENOFF(cen, cenpos);
@@ -808,10 +931,10 @@
checkZIP64(cen, cenpos);
}
// negative for lazy initialization, see getDataOffset();
- pos = - (pos + ZipFile.this.zsrc.locpos);
+ pos = - (pos + ZipFile.this.res.zsrc.locpos);
}
- private void checkZIP64(byte[] cen, int cenpos) throws IOException {
+ private void checkZIP64(byte[] cen, int cenpos) {
int off = cenpos + CENHDR + CENNAM(cen, cenpos);
int end = off + CENEXT(cen, cenpos);
while (off + 4 < end) {
@@ -857,7 +980,7 @@
if (pos <= 0) {
byte[] loc = new byte[LOCHDR];
pos = -pos;
- int len = ZipFile.this.zsrc.readFullyAt(loc, 0, loc.length, pos);
+ int len = ZipFile.this.res.zsrc.readFullyAt(loc, 0, loc.length, pos);
if (len != LOCHDR) {
throw new ZipException("ZipFile error reading zip file");
}
@@ -882,7 +1005,7 @@
if (len <= 0) {
return 0;
}
- len = ZipFile.this.zsrc.readAt(b, off, len, pos);
+ len = ZipFile.this.res.zsrc.readAt(b, off, len, pos);
if (len > 0) {
pos += len;
rem -= len;
@@ -932,15 +1055,11 @@
}
closeRequested = true;
rem = 0;
- synchronized (streams) {
- streams.remove(this);
+ synchronized (res.istreams) {
+ res.istreams.remove(this);
}
}
- @SuppressWarnings("deprecation")
- protected void finalize() {
- close();
- }
}
/**
@@ -952,6 +1071,7 @@
private String[] getMetaInfEntryNames() {
synchronized (this) {
ensureOpen();
+ Source zsrc = res.zsrc;
if (zsrc.metanames == null) {
return null;
}
@@ -972,7 +1092,7 @@
new JavaUtilZipFileAccess() {
@Override
public boolean startsWithLocHeader(ZipFile zip) {
- return zip.zsrc.startsWithLoc;
+ return zip.res.zsrc.startsWithLoc;
}
@Override
public String[] getMetaInfEntryNames(ZipFile zip) {
@@ -1080,7 +1200,7 @@
private static final HashMap files = new HashMap<>();
- public static Source get(File file, boolean toDelete) throws IOException {
+ static Source get(File file, boolean toDelete) throws IOException {
Key key = new Key(file,
Files.readAttributes(file.toPath(), BasicFileAttributes.class));
Source src = null;
@@ -1105,9 +1225,9 @@
}
}
- private static void close(Source src) throws IOException {
+ static void release(Source src) throws IOException {
synchronized (files) {
- if (--src.refs == 0) {
+ if (src != null && --src.refs == 0) {
files.remove(src.key);
src.close();
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java
--- a/src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaIOFileDescriptorAccess.java Thu Dec 14 12:28:32 2017 +0000
@@ -25,6 +25,7 @@
package jdk.internal.misc;
import java.io.FileDescriptor;
+import java.io.IOException;
/*
* @author Chris Hegarty
@@ -35,7 +36,8 @@
public int get(FileDescriptor fdo);
public void setAppend(FileDescriptor fdo, boolean append);
public boolean getAppend(FileDescriptor fdo);
- public void close(FileDescriptor fdo);
+ public void close(FileDescriptor fdo) throws IOException;
+ public void registerCleanup(FileDescriptor fdo);
// Only valid on Windows
public void setHandle(FileDescriptor fdo, long handle);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java
--- a/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/misc/JavaLangAccess.java Thu Dec 14 12:28:32 2017 +0000
@@ -254,4 +254,23 @@
* given class loader.
*/
Stream layers(ClassLoader loader);
+
+ /**
+ * Returns a new string by decoding from the given utf8 bytes array.
+ *
+ * @param off the index of the first byte to decode
+ * @param len the number of bytes to decode
+ * @return the newly created string
+ * @throws IllegalArgumentException for malformed or unmappable bytes.
+ */
+ String newStringUTF8NoRepl(byte[] bytes, int off, int len);
+
+ /**
+ * Encode the given string into a sequence of bytes using utf8.
+ *
+ * @param s the string to encode
+ * @return the encoded bytes in utf8
+ * @throws IllegalArgumentException for malformed surrogates
+ */
+ byte[] getBytesUTF8NoRepl(String s);
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/module/ModuleInfo.java
--- a/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfo.java Thu Dec 14 12:28:32 2017 +0000
@@ -63,6 +63,9 @@
public final class ModuleInfo {
+ private final int JAVA_MIN_SUPPORTED_VERSION = 53;
+ private final int JAVA_MAX_SUPPORTED_VERSION = 54;
+
private static final JavaLangModuleAccess JLMA
= SharedSecrets.getJavaLangModuleAccess();
@@ -188,8 +191,10 @@
int minor_version = in.readUnsignedShort();
int major_version = in.readUnsignedShort();
- if (major_version < 53) {
- throw invalidModuleDescriptor("Must be >= 53.0");
+ if (major_version < JAVA_MIN_SUPPORTED_VERSION ||
+ major_version > JAVA_MAX_SUPPORTED_VERSION) {
+ throw invalidModuleDescriptor("Unsupported major.minor version "
+ + major_version + "." + minor_version);
}
ConstantPool cpool = new ConstantPool(in);
@@ -245,7 +250,7 @@
switch (attribute_name) {
case MODULE :
- builder = readModuleAttribute(in, cpool);
+ builder = readModuleAttribute(in, cpool, major_version);
break;
case MODULE_PACKAGES :
@@ -334,7 +339,7 @@
* Reads the Module attribute, returning the ModuleDescriptor.Builder to
* build the corresponding ModuleDescriptor.
*/
- private Builder readModuleAttribute(DataInput in, ConstantPool cpool)
+ private Builder readModuleAttribute(DataInput in, ConstantPool cpool, int major)
throws IOException
{
// module_name
@@ -390,8 +395,21 @@
JLMA.requires(builder, mods, dn, vs);
}
- if (dn.equals("java.base"))
+ if (dn.equals("java.base")) {
+ if (major >= 54
+ && (mods.contains(Requires.Modifier.TRANSITIVE)
+ || mods.contains(Requires.Modifier.STATIC))) {
+ String flagName;
+ if (mods.contains(Requires.Modifier.TRANSITIVE)) {
+ flagName = "ACC_TRANSITIVE";
+ } else {
+ flagName = "ACC_STATIC_PHASE";
+ }
+ throw invalidModuleDescriptor("The requires entry for java.base"
+ + " has " + flagName + " set");
+ }
requiresJavaBase = true;
+ }
}
if (mn.equals("java.base")) {
if (requires_count > 0) {
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java
--- a/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Thu Dec 14 12:28:32 2017 +0000
@@ -80,7 +80,7 @@
*/
private static byte[] toModuleInfo(ModuleDescriptor md, ModuleTarget target) {
ClassWriter cw = new ClassWriter(0);
- cw.visit(Opcodes.V9, ACC_MODULE, "module-info", null, null, null);
+ cw.visit(Opcodes.V10, ACC_MODULE, "module-info", null, null, null);
int moduleFlags = md.modifiers().stream()
.map(MODULE_MODS_TO_FLAGS::get)
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java
--- a/src/java.base/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/util/xml/PropertiesDefaultHandler.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* 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 jdk.internal.util.xml;
import java.io.*;
+import java.nio.charset.Charset;
import java.util.InvalidPropertiesFormatException;
import java.util.Map.Entry;
import java.util.Properties;
@@ -94,11 +95,11 @@
*/
}
- public void store(Properties props, OutputStream os, String comment, String encoding)
+ public void store(Properties props, OutputStream os, String comment, Charset charset)
throws IOException
{
try {
- XMLStreamWriter writer = new XMLStreamWriterImpl(os, encoding);
+ XMLStreamWriter writer = new XMLStreamWriterImpl(os, charset);
writer.writeStartDocument();
writer.writeDTD(PROPS_DTD_DECL);
writer.writeStartElement(ELEMENT_ROOT);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/util/xml/XMLStreamWriter.java
--- a/src/java.base/share/classes/jdk/internal/util/xml/XMLStreamWriter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/util/xml/XMLStreamWriter.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,9 @@
package jdk.internal.util.xml;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
/**
* Basic XMLStreamWriter for writing simple XML files such as those
* defined in java.util.Properties
@@ -38,6 +41,7 @@
//Defaults the XML version to 1.0, and the encoding to utf-8
public static final String DEFAULT_XML_VERSION = "1.0";
public static final String DEFAULT_ENCODING = "UTF-8";
+ public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
/**
* Writes a start tag to the output. All writeStartElement methods
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/jdk/internal/util/xml/impl/XMLStreamWriterImpl.java
--- a/src/java.base/share/classes/jdk/internal/util/xml/impl/XMLStreamWriterImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/jdk/internal/util/xml/impl/XMLStreamWriterImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,7 +66,7 @@
private int _state = 0;
private Element _currentEle;
private XMLWriter _writer;
- private String _encoding;
+ private Charset _charset;
/**
* This flag can be used to turn escaping off for content. It does
* not apply to attribute content.
@@ -79,26 +79,23 @@
System.getProperty("line.separator").toCharArray();
public XMLStreamWriterImpl(OutputStream os) throws XMLStreamException {
- this(os, XMLStreamWriter.DEFAULT_ENCODING);
+ this(os, XMLStreamWriter.DEFAULT_CHARSET);
}
- public XMLStreamWriterImpl(OutputStream os, String encoding)
+ public XMLStreamWriterImpl(OutputStream os, Charset cs)
throws XMLStreamException
{
- Charset cs = null;
- if (encoding == null) {
- _encoding = XMLStreamWriter.DEFAULT_ENCODING;
+ if (cs == null) {
+ _charset = XMLStreamWriter.DEFAULT_CHARSET;
} else {
try {
- cs = getCharset(encoding);
+ _charset = checkCharset(cs);
} catch (UnsupportedEncodingException e) {
throw new XMLStreamException(e);
}
-
- this._encoding = encoding;
}
- _writer = new XMLWriter(os, encoding, cs);
+ _writer = new XMLWriter(os, null, _charset);
}
/**
@@ -108,7 +105,7 @@
* @throws XMLStreamException
*/
public void writeStartDocument() throws XMLStreamException {
- writeStartDocument(_encoding, XMLStreamWriter.DEFAULT_XML_VERSION);
+ writeStartDocument(_charset.name(), XMLStreamWriter.DEFAULT_XML_VERSION);
}
/**
@@ -118,7 +115,7 @@
* @throws XMLStreamException
*/
public void writeStartDocument(String version) throws XMLStreamException {
- writeStartDocument(_encoding, version, null);
+ writeStartDocument(_charset.name(), version, null);
}
/**
@@ -155,7 +152,7 @@
_state = STATE_XML_DECL;
String enc = encoding;
if (enc == null) {
- enc = _encoding;
+ enc = _charset.name();
} else {
//check if the encoding is supported
try {
@@ -564,6 +561,20 @@
return cs;
}
+ /**
+ * Checks for charset support.
+ * @param charset the specified charset
+ * @return the charset
+ * @throws UnsupportedEncodingException if the charset is not supported
+ */
+ private Charset checkCharset(Charset charset) throws UnsupportedEncodingException {
+ if (charset.name().equalsIgnoreCase("UTF-32")) {
+ throw new UnsupportedEncodingException("The basic XMLWriter does "
+ + "not support " + charset.name());
+ }
+ return charset;
+ }
+
/*
* Start of Internal classes.
*
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/launcher/LauncherHelper.java
--- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java Thu Dec 14 12:28:32 2017 +0000
@@ -268,7 +268,7 @@
Locale locale = Locale.getDefault();
ostream.println(LOCALE_SETTINGS);
ostream.println(INDENT + "default locale = " +
- locale.getDisplayLanguage());
+ locale.getDisplayName());
ostream.println(INDENT + "default display locale = " +
Locale.getDefault(Category.DISPLAY).getDisplayName());
ostream.println(INDENT + "default format locale = " +
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -27,6 +27,7 @@
import java.io.FileDescriptor;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.lang.ref.Cleaner.Cleanable;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
@@ -109,7 +110,12 @@
}
public void run() {
- fdAccess.close(fd);
+ try {
+ fdAccess.close(fd);
+ } catch (IOException ioe) {
+ // Rethrow as unchecked so the exception can be propagated as needed
+ throw new UncheckedIOException("close", ioe);
+ }
}
}
@@ -188,7 +194,11 @@
} else if (closer != null) {
// Perform the cleaning action so it is not redone when
// this channel becomes phantom reachable.
- closer.clean();
+ try {
+ closer.clean();
+ } catch (UncheckedIOException uioe) {
+ throw uioe.getCause();
+ }
} else {
fdAccess.close(fd);
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java
--- a/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java Thu Dec 14 12:28:32 2017 +0000
@@ -63,8 +63,8 @@
return new Encoder(this);
}
- private static class Decoder extends CharsetDecoder
- implements ArrayDecoder {
+ private static class Decoder extends CharsetDecoder {
+
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
@@ -124,23 +124,10 @@
else
return decodeBufferLoop(src, dst);
}
-
- public int decode(byte[] src, int sp, int len, char[] dst) {
- if (len > dst.length)
- len = dst.length;
- int dp = 0;
- while (dp < len)
- dst[dp++] = (char)(src[sp++] & 0xff);
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
- private static class Encoder extends CharsetEncoder
- implements ArrayEncoder {
+ private static class Encoder extends CharsetEncoder {
+
private Encoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
@@ -271,39 +258,5 @@
else
return encodeBufferLoop(src, dst);
}
-
- private byte repl = (byte)'?';
- protected void implReplaceWith(byte[] newReplacement) {
- repl = newReplacement[0];
- }
-
- public int encode(char[] src, int sp, int len, byte[] dst) {
- int dp = 0;
- int slen = Math.min(len, dst.length);
- int sl = sp + slen;
- while (sp < sl) {
- int ret = encodeISOArray(src, sp, dst, dp, slen);
- sp = sp + ret;
- dp = dp + ret;
- if (ret != slen) {
- char c = src[sp++];
- if (Character.isHighSurrogate(c) && sp < sl &&
- Character.isLowSurrogate(src[sp])) {
- if (len > dst.length) {
- sl++;
- len--;
- }
- sp++;
- }
- dst[dp++] = repl;
- slen = Math.min((sl - sp), (dst.length - dp));
- }
- }
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/nio/cs/US_ASCII.java
--- a/src/java.base/share/classes/sun/nio/cs/US_ASCII.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/nio/cs/US_ASCII.java Thu Dec 14 12:28:32 2017 +0000
@@ -58,8 +58,7 @@
return new Encoder(this);
}
- private static class Decoder extends CharsetDecoder
- implements ArrayDecoder {
+ private static class Decoder extends CharsetDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
@@ -128,32 +127,9 @@
else
return decodeBufferLoop(src, dst);
}
-
- private char repl = '\uFFFD';
- protected void implReplaceWith(String newReplacement) {
- repl = newReplacement.charAt(0);
- }
-
- public int decode(byte[] src, int sp, int len, char[] dst) {
- int dp = 0;
- len = Math.min(len, dst.length);
- while (dp < len) {
- byte b = src[sp++];
- if (b >= 0)
- dst[dp++] = (char)b;
- else
- dst[dp++] = repl;
- }
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
- private static class Encoder extends CharsetEncoder
- implements ArrayEncoder {
+ private static class Encoder extends CharsetEncoder {
private Encoder(Charset cs) {
super(cs, 1.0f, 1.0f);
@@ -237,36 +213,5 @@
return encodeBufferLoop(src, dst);
}
- private byte repl = (byte)'?';
- protected void implReplaceWith(byte[] newReplacement) {
- repl = newReplacement[0];
- }
-
- public int encode(char[] src, int sp, int len, byte[] dst) {
- int dp = 0;
- int sl = sp + Math.min(len, dst.length);
- while (sp < sl) {
- char c = src[sp++];
- if (c < 0x80) {
- dst[dp++] = (byte)c;
- continue;
- }
- if (Character.isHighSurrogate(c) && sp < sl &&
- Character.isLowSurrogate(src[sp])) {
- if (len > dst.length) {
- sl++;
- len--;
- }
- sp++;
- }
- dst[dp++] = repl;
- }
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
-
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/nio/cs/UTF_8.java
--- a/src/java.base/share/classes/sun/nio/cs/UTF_8.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/nio/cs/UTF_8.java Thu Dec 14 12:28:32 2017 +0000
@@ -80,8 +80,8 @@
dst.position(dp - dst.arrayOffset());
}
- private static class Decoder extends CharsetDecoder
- implements ArrayDecoder {
+ private static class Decoder extends CharsetDecoder {
+
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
@@ -423,142 +423,9 @@
bb.position(sp);
return bb;
}
-
- // returns -1 if there is/are malformed byte(s) and the
- // "action" for malformed input is not REPLACE.
- public int decode(byte[] sa, int sp, int len, char[] da) {
- final int sl = sp + len;
- int dp = 0;
- int dlASCII = Math.min(len, da.length);
- ByteBuffer bb = null; // only necessary if malformed
-
- // ASCII only optimized loop
- while (dp < dlASCII && sa[sp] >= 0)
- da[dp++] = (char) sa[sp++];
-
- while (sp < sl) {
- int b1 = sa[sp++];
- if (b1 >= 0) {
- // 1 byte, 7 bits: 0xxxxxxx
- da[dp++] = (char) b1;
- } else if ((b1 >> 5) == -2 && (b1 & 0x1e) != 0) {
- // 2 bytes, 11 bits: 110xxxxx 10xxxxxx
- if (sp < sl) {
- int b2 = sa[sp++];
- if (isNotContinuation(b2)) {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- sp--; // malformedN(bb, 2) always returns 1
- } else {
- da[dp++] = (char) (((b1 << 6) ^ b2)^
- (((byte) 0xC0 << 6) ^
- ((byte) 0x80 << 0)));
- }
- continue;
- }
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- return dp;
- } else if ((b1 >> 4) == -2) {
- // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx
- if (sp + 1 < sl) {
- int b2 = sa[sp++];
- int b3 = sa[sp++];
- if (isMalformed3(b1, b2, b3)) {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- sp -= 3;
- bb = getByteBuffer(bb, sa, sp);
- sp += malformedN(bb, 3).length();
- } else {
- char c = (char)((b1 << 12) ^
- (b2 << 6) ^
- (b3 ^
- (((byte) 0xE0 << 12) ^
- ((byte) 0x80 << 6) ^
- ((byte) 0x80 << 0))));
- if (Character.isSurrogate(c)) {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- } else {
- da[dp++] = c;
- }
- }
- continue;
- }
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- if (sp < sl && isMalformed3_2(b1, sa[sp])) {
- da[dp++] = replacement().charAt(0);
- continue;
-
- }
- da[dp++] = replacement().charAt(0);
- return dp;
- } else if ((b1 >> 3) == -2) {
- // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- if (sp + 2 < sl) {
- int b2 = sa[sp++];
- int b3 = sa[sp++];
- int b4 = sa[sp++];
- int uc = ((b1 << 18) ^
- (b2 << 12) ^
- (b3 << 6) ^
- (b4 ^
- (((byte) 0xF0 << 18) ^
- ((byte) 0x80 << 12) ^
- ((byte) 0x80 << 6) ^
- ((byte) 0x80 << 0))));
- if (isMalformed4(b2, b3, b4) ||
- // shortest form check
- !Character.isSupplementaryCodePoint(uc)) {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- sp -= 4;
- bb = getByteBuffer(bb, sa, sp);
- sp += malformedN(bb, 4).length();
- } else {
- da[dp++] = Character.highSurrogate(uc);
- da[dp++] = Character.lowSurrogate(uc);
- }
- continue;
- }
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- b1 &= 0xff;
- if (b1 > 0xf4 ||
- sp < sl && isMalformed4_2(b1, sa[sp] & 0xff)) {
- da[dp++] = replacement().charAt(0);
- continue;
- }
- sp++;
- if (sp < sl && isMalformed4_3(sa[sp])) {
- da[dp++] = replacement().charAt(0);
- continue;
- }
- da[dp++] = replacement().charAt(0);
- return dp;
- } else {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = replacement().charAt(0);
- }
- }
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
- private static final class Encoder extends CharsetEncoder
- implements ArrayEncoder {
+ private static final class Encoder extends CharsetEncoder {
private Encoder(Charset cs) {
super(cs, 1.1f, 3.0f);
@@ -699,58 +566,5 @@
return encodeBufferLoop(src, dst);
}
- private byte repl = (byte)'?';
- protected void implReplaceWith(byte[] newReplacement) {
- repl = newReplacement[0];
- }
-
- // returns -1 if there is malformed char(s) and the
- // "action" for malformed input is not REPLACE.
- public int encode(char[] sa, int sp, int len, byte[] da) {
- int sl = sp + len;
- int dp = 0;
- int dlASCII = dp + Math.min(len, da.length);
-
- // ASCII only optimized loop
- while (dp < dlASCII && sa[sp] < '\u0080')
- da[dp++] = (byte) sa[sp++];
-
- while (sp < sl) {
- char c = sa[sp++];
- if (c < 0x80) {
- // Have at most seven bits
- da[dp++] = (byte)c;
- } else if (c < 0x800) {
- // 2 bytes, 11 bits
- da[dp++] = (byte)(0xc0 | (c >> 6));
- da[dp++] = (byte)(0x80 | (c & 0x3f));
- } else if (Character.isSurrogate(c)) {
- if (sgp == null)
- sgp = new Surrogate.Parser();
- int uc = sgp.parse(c, sa, sp - 1, sl);
- if (uc < 0) {
- if (malformedInputAction() != CodingErrorAction.REPLACE)
- return -1;
- da[dp++] = repl;
- } else {
- da[dp++] = (byte)(0xf0 | ((uc >> 18)));
- da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f));
- da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f));
- da[dp++] = (byte)(0x80 | (uc & 0x3f));
- sp++; // 2 chars
- }
- } else {
- // 3 bytes, 16 bits
- da[dp++] = (byte)(0xe0 | ((c >> 12)));
- da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f));
- da[dp++] = (byte)(0x80 | (c & 0x3f));
- }
- }
- return dp;
- }
-
- public boolean isASCIICompatible() {
- return true;
- }
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java
--- a/src/java.base/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
private final SecretKey premasterSecret;
private final int majorVersion, minorVersion;
private final byte[] clientRandom, serverRandom;
+ private final byte[] extendedMasterSecretSessionHash;
private final String prfHashAlg;
private final int prfHashLength;
private final int prfBlockSize;
@@ -80,6 +81,50 @@
int majorVersion, int minorVersion,
byte[] clientRandom, byte[] serverRandom,
String prfHashAlg, int prfHashLength, int prfBlockSize) {
+ this(premasterSecret, majorVersion, minorVersion,
+ clientRandom, serverRandom,
+ new byte[0],
+ prfHashAlg, prfHashLength, prfBlockSize);
+ }
+
+ /**
+ * Constructs a new TlsMasterSecretParameterSpec.
+ *
+ *
The getAlgorithm() method of premasterSecret
+ * should return "TlsRsaPremasterSecret" if the key exchange
+ * algorithm was RSA and "TlsPremasterSecret" otherwise.
+ *
+ * @param premasterSecret the premaster secret
+ * @param majorVersion the major number of the protocol version
+ * @param minorVersion the minor number of the protocol version
+ * @param extendedMasterSecretSessionHash the session hash for
+ * Extended Master Secret
+ * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+ * Used only for TLS 1.2+. TLS1.1 and earlier use a fixed PRF.
+ * @param prfHashLength the output length of the TLS PRF hash algorithm.
+ * Used only for TLS 1.2+.
+ * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+ * Used only for TLS 1.2+.
+ *
+ * @throws NullPointerException if premasterSecret is null
+ * @throws IllegalArgumentException if minorVersion or majorVersion are
+ * negative or larger than 255
+ */
+ public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
+ int majorVersion, int minorVersion,
+ byte[] extendedMasterSecretSessionHash,
+ String prfHashAlg, int prfHashLength, int prfBlockSize) {
+ this(premasterSecret, majorVersion, minorVersion,
+ new byte[0], new byte[0],
+ extendedMasterSecretSessionHash,
+ prfHashAlg, prfHashLength, prfBlockSize);
+ }
+
+ private TlsMasterSecretParameterSpec(SecretKey premasterSecret,
+ int majorVersion, int minorVersion,
+ byte[] clientRandom, byte[] serverRandom,
+ byte[] extendedMasterSecretSessionHash,
+ String prfHashAlg, int prfHashLength, int prfBlockSize) {
if (premasterSecret == null) {
throw new NullPointerException("premasterSecret must not be null");
}
@@ -88,6 +133,9 @@
this.minorVersion = checkVersion(minorVersion);
this.clientRandom = clientRandom.clone();
this.serverRandom = serverRandom.clone();
+ this.extendedMasterSecretSessionHash =
+ (extendedMasterSecretSessionHash != null ?
+ extendedMasterSecretSessionHash.clone() : new byte[0]);
this.prfHashAlg = prfHashAlg;
this.prfHashLength = prfHashLength;
this.prfBlockSize = prfBlockSize;
@@ -147,6 +195,17 @@
}
/**
+ * Returns a copy of the Extended Master Secret session hash.
+ *
+ * @return a copy of the Extended Master Secret session hash, or an empty
+ * array if no extended master secret session hash was provided
+ * at instantiation time
+ */
+ public byte[] getExtendedMasterSecretSessionHash() {
+ return extendedMasterSecretSessionHash.clone();
+ }
+
+ /**
* Obtains the PRF hash algorithm to use in the PRF calculation.
*
* @return the hash algorithm.
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java
--- a/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java Thu Dec 14 12:28:32 2017 +0000
@@ -655,7 +655,8 @@
// validate subject identity
ClientKeyExchangeService p =
- ClientKeyExchangeService.find(sessionSuite.keyExchange.name);
+ ClientKeyExchangeService.find(
+ sessionSuite.keyExchange.name);
if (p != null) {
Principal localPrincipal = session.getLocalPrincipal();
@@ -663,8 +664,9 @@
if (debug != null && Debug.isOn("session"))
System.out.println("Subject identity is same");
} else {
- throw new SSLProtocolException("Server resumed" +
- " session with wrong subject identity or no subject");
+ throw new SSLProtocolException(
+ "Server resumed session with " +
+ "wrong subject identity or no subject");
}
}
@@ -707,6 +709,54 @@
} // Otherwise, using the value negotiated during the original
// session initiation
+ // check the "extended_master_secret" extension
+ ExtendedMasterSecretExtension extendedMasterSecretExt =
+ (ExtendedMasterSecretExtension)mesg.extensions.get(
+ ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+ if (extendedMasterSecretExt != null) {
+ // Is it the expected server extension?
+ if (!useExtendedMasterSecret ||
+ !mesgVersion.useTLS10PlusSpec() || !requestedToUseEMS) {
+ fatalSE(Alerts.alert_unsupported_extension,
+ "Server sent the extended_master_secret " +
+ "extension improperly");
+ }
+
+ // For abbreviated handshake, if the original session did not use
+ // the "extended_master_secret" extension but the new ServerHello
+ // contains the extension, the client MUST abort the handshake.
+ if (resumingSession && (session != null) &&
+ !session.getUseExtendedMasterSecret()) {
+ fatalSE(Alerts.alert_unsupported_extension,
+ "Server sent an unexpected extended_master_secret " +
+ "extension on session resumption");
+ }
+ } else {
+ if (useExtendedMasterSecret && !allowLegacyMasterSecret) {
+ // For full handshake, if a client receives a ServerHello
+ // without the extension, it SHOULD abort the handshake if
+ // it does not wish to interoperate with legacy servers.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Extended Master Secret extension is required");
+ }
+
+ if (resumingSession && (session != null)) {
+ if (session.getUseExtendedMasterSecret()) {
+ // For abbreviated handshake, if the original session used
+ // the "extended_master_secret" extension but the new
+ // ServerHello does not contain the extension, the client
+ // MUST abort the handshake.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Missing Extended Master Secret extension " +
+ "on session resumption");
+ } else if (useExtendedMasterSecret && !allowLegacyResumption) {
+ // Unlikely, abbreviated handshake should be discarded.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Extended Master Secret extension is required");
+ }
+ }
+ }
+
// check the ALPN extension
ALPNExtension serverHelloALPN =
(ALPNExtension) mesg.extensions.get(ExtensionType.EXT_ALPN);
@@ -777,7 +827,8 @@
&& (type != ExtensionType.EXT_ALPN)
&& (type != ExtensionType.EXT_RENEGOTIATION_INFO)
&& (type != ExtensionType.EXT_STATUS_REQUEST)
- && (type != ExtensionType.EXT_STATUS_REQUEST_V2)) {
+ && (type != ExtensionType.EXT_STATUS_REQUEST_V2)
+ && (type != ExtensionType.EXT_EXTENDED_MASTER_SECRET)) {
// Note: Better to check client requested extensions rather
// than all supported extensions.
fatalSE(Alerts.alert_unsupported_extension,
@@ -788,7 +839,8 @@
// Create a new session, we need to do the full handshake
session = new SSLSessionImpl(protocolVersion, cipherSuite,
getLocalSupportedSignAlgs(),
- mesg.sessionId, getHostSE(), getPortSE());
+ mesg.sessionId, getHostSE(), getPortSE(),
+ (extendedMasterSecretExt != null));
session.setRequestedServerNames(requestedServerNames);
session.setNegotiatedMaxFragSize(requestedMFLength);
session.setMaximumPacketSize(maximumPacketSize);
@@ -1430,6 +1482,44 @@
session = null;
}
+ if ((session != null) && useExtendedMasterSecret) {
+ boolean isTLS10Plus = sessionVersion.useTLS10PlusSpec();
+ if (isTLS10Plus && !session.getUseExtendedMasterSecret()) {
+ if (!allowLegacyResumption) {
+ // perform full handshake instead
+ //
+ // The client SHOULD NOT offer an abbreviated handshake
+ // to resume a session that does not use an extended
+ // master secret. Instead, it SHOULD offer a full
+ // handshake.
+ session = null;
+ }
+ }
+
+ if ((session != null) && !allowUnsafeServerCertChange) {
+ // It is fine to move on with abbreviate handshake if
+ // endpoint identification is enabled.
+ String identityAlg = getEndpointIdentificationAlgorithmSE();
+ if ((identityAlg == null || identityAlg.length() == 0)) {
+ if (isTLS10Plus) {
+ if (!session.getUseExtendedMasterSecret()) {
+ // perform full handshake instead
+ session = null;
+ } // Otherwise, use extended master secret.
+ } else {
+ // The extended master secret extension does not
+ // apply to SSL 3.0. Perform a full handshake
+ // instead.
+ //
+ // Note that the useExtendedMasterSecret is
+ // extended to protect SSL 3.0 connections,
+ // by discarding abbreviate handshake.
+ session = null;
+ }
+ }
+ }
+ }
+
if (session != null) {
if (debug != null) {
if (Debug.isOn("handshake") || Debug.isOn("session")) {
@@ -1539,6 +1629,14 @@
clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
}
+ // add Extended Master Secret extension
+ if (useExtendedMasterSecret && maxProtocolVersion.useTLS10PlusSpec()) {
+ if ((session == null) || session.getUseExtendedMasterSecret()) {
+ clientHelloMessage.addExtendedMasterSecretExtension();
+ requestedToUseEMS = true;
+ }
+ }
+
// add server_name extension
if (enableSNIExtension) {
if (session != null) {
@@ -1647,10 +1745,14 @@
// Allow server certificate change in client side during renegotiation
// after a session-resumption abbreviated initial handshake?
//
- // DO NOT need to check allowUnsafeServerCertChange here. We only
+ // DO NOT need to check allowUnsafeServerCertChange here. We only
// reserve server certificates when allowUnsafeServerCertChange is
// flase.
- if (reservedServerCerts != null) {
+ //
+ // Allow server certificate change if it is negotiated to use the
+ // extended master secret.
+ if ((reservedServerCerts != null) &&
+ !session.getUseExtendedMasterSecret()) {
// It is not necessary to check the certificate update if endpoint
// identification is enabled.
String identityAlg = getEndpointIdentificationAlgorithmSE();
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java Thu Dec 14 12:28:32 2017 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.security.ssl;
+
+import java.io.IOException;
+import javax.net.ssl.SSLProtocolException;
+
+/**
+ * Extended Master Secret TLS extension (TLS 1.0+). This extension
+ * defines how to calculate the TLS connection master secret and
+ * mitigates some types of man-in-the-middle attacks.
+ *
+ * See further information in
+ * RFC 7627.
+ *
+ * @author Martin Balao (mbalao@redhat.com)
+ */
+final class ExtendedMasterSecretExtension extends HelloExtension {
+ ExtendedMasterSecretExtension() {
+ super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+ }
+
+ ExtendedMasterSecretExtension(HandshakeInStream s,
+ int len) throws IOException {
+ super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+
+ if (len != 0) {
+ throw new SSLProtocolException("Invalid " + type + " extension");
+ }
+ }
+
+ @Override
+ int length() {
+ return 4; // 4: extension type and length fields
+ }
+
+ @Override
+ void send(HandshakeOutStream s) throws IOException {
+ s.putInt16(type.id); // ExtensionType extension_type;
+ s.putInt16(0); // extension_data length
+ }
+
+ @Override
+ public String toString() {
+ return "Extension " + type;
+ }
+}
+
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/ExtensionType.java
--- a/src/java.base/share/classes/sun/security/ssl/ExtensionType.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ExtensionType.java Thu Dec 14 12:28:32 2017 +0000
@@ -43,7 +43,7 @@
return name;
}
- static List knownExtensions = new ArrayList<>(15);
+ static List knownExtensions = new ArrayList<>(16);
static ExtensionType get(int id) {
for (ExtensionType ext : knownExtensions) {
@@ -105,6 +105,10 @@
static final ExtensionType EXT_STATUS_REQUEST_V2 =
e(0x0011, "status_request_v2"); // IANA registry value: 17
+ // extensions defined in RFC 7627
+ static final ExtensionType EXT_EXTENDED_MASTER_SECRET =
+ e(0x0017, "extended_master_secret"); // IANA registry value: 23
+
// extensions defined in RFC 5746
static final ExtensionType EXT_RENEGOTIATION_INFO =
e(0xff01, "renegotiation_info"); // IANA registry value: 65281
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java
--- a/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/HandshakeMessage.java Thu Dec 14 12:28:32 2017 +0000
@@ -389,6 +389,10 @@
extensions.add(signatureAlgorithm);
}
+ void addExtendedMasterSecretExtension() {
+ extensions.add(new ExtendedMasterSecretExtension());
+ }
+
void addMFLExtension(int maximumPacketSize) {
HelloExtension maxFragmentLength =
new MaxFragmentLengthExtension(maximumPacketSize);
@@ -1441,7 +1445,7 @@
} else {
sig = getSignature(privateKey.getAlgorithm());
}
- sig.initSign(privateKey); // where is the SecureRandom?
+ sig.initSign(privateKey, sr);
updateSignature(sig, clntNonce, svrNonce);
signatureBytes = sig.sign();
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/Handshaker.java
--- a/src/java.base/share/classes/sun/security/ssl/Handshaker.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/Handshaker.java Thu Dec 14 12:28:32 2017 +0000
@@ -30,12 +30,6 @@
import java.util.*;
import java.security.*;
import java.nio.ByteBuffer;
-import java.security.NoSuchAlgorithmException;
-import java.security.AccessController;
-import java.security.AlgorithmConstraints;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
import java.util.function.BiFunction;
import javax.crypto.*;
@@ -225,6 +219,20 @@
Debug.getBooleanProperty(
"jdk.tls.rejectClientInitiatedRenegotiation", false);
+ // To switch off the extended_master_secret extension.
+ static final boolean useExtendedMasterSecret;
+
+ // Allow session resumption without Extended Master Secret extension.
+ static final boolean allowLegacyResumption =
+ Debug.getBooleanProperty("jdk.tls.allowLegacyResumption", true);
+
+ // Allow full handshake without Extended Master Secret extension.
+ static final boolean allowLegacyMasterSecret =
+ Debug.getBooleanProperty("jdk.tls.allowLegacyMasterSecret", true);
+
+ // Is it requested to use extended master secret extension?
+ boolean requestedToUseEMS = false;
+
// need to dispose the object when it is invalidated
boolean invalidated;
@@ -233,6 +241,24 @@
*/
final boolean isDTLS;
+ // Is the extended_master_secret extension supported?
+ static {
+ boolean supportExtendedMasterSecret = true;
+ try {
+ KeyGenerator kg =
+ JsseJce.getKeyGenerator("SunTlsExtendedMasterSecret");
+ } catch (NoSuchAlgorithmException nae) {
+ supportExtendedMasterSecret = false;
+ }
+
+ if (supportExtendedMasterSecret) {
+ useExtendedMasterSecret = Debug.getBooleanProperty(
+ "jdk.tls.useExtendedMasterSecret", true);
+ } else {
+ useExtendedMasterSecret = false;
+ }
+ }
+
Handshaker(SSLSocketImpl c, SSLContextImpl context,
ProtocolList enabledProtocols, boolean needCertVerify,
boolean isClient, ProtocolVersion activeProtocolVersion,
@@ -243,7 +269,7 @@
init(context, enabledProtocols, needCertVerify, isClient,
activeProtocolVersion, isInitialHandshake, secureRenegotiation,
clientVerifyData, serverVerifyData);
- }
+ }
Handshaker(SSLEngineImpl engine, SSLContextImpl context,
ProtocolList enabledProtocols, boolean needCertVerify,
@@ -1226,6 +1252,7 @@
* SHA1 hashes are of (different) constant strings, the pre-master
* secret, and the nonces provided by the client and the server.
*/
+ @SuppressWarnings("deprecation")
private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
ProtocolVersion requestedVersion) {
@@ -1276,11 +1303,37 @@
int prfHashLength = prf.getPRFHashLength();
int prfBlockSize = prf.getPRFBlockSize();
- @SuppressWarnings("deprecation")
- TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
- preMasterSecret, (majorVersion & 0xFF), (minorVersion & 0xFF),
- clnt_random.random_bytes, svr_random.random_bytes,
- prfHashAlg, prfHashLength, prfBlockSize);
+ TlsMasterSecretParameterSpec spec;
+ if (session.getUseExtendedMasterSecret()) {
+ // reset to use the extended master secret algorithm
+ masterAlg = "SunTlsExtendedMasterSecret";
+
+ byte[] sessionHash = null;
+ if (protocolVersion.useTLS12PlusSpec()) {
+ sessionHash = handshakeHash.getFinishedHash();
+ } else {
+ // TLS 1.0/1.1, DTLS 1.0
+ sessionHash = new byte[36];
+ try {
+ handshakeHash.getMD5Clone().digest(sessionHash, 0, 16);
+ handshakeHash.getSHAClone().digest(sessionHash, 16, 20);
+ } catch (DigestException de) {
+ throw new ProviderException(de);
+ }
+ }
+
+ spec = new TlsMasterSecretParameterSpec(
+ preMasterSecret,
+ (majorVersion & 0xFF), (minorVersion & 0xFF),
+ sessionHash,
+ prfHashAlg, prfHashLength, prfBlockSize);
+ } else {
+ spec = new TlsMasterSecretParameterSpec(
+ preMasterSecret,
+ (majorVersion & 0xFF), (minorVersion & 0xFF),
+ clnt_random.random_bytes, svr_random.random_bytes,
+ prfHashAlg, prfHashLength, prfBlockSize);
+ }
try {
KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/HelloExtensions.java
--- a/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/HelloExtensions.java Thu Dec 14 12:28:32 2017 +0000
@@ -93,6 +93,8 @@
extension = new CertStatusReqExtension(s, extlen);
} else if (extType == ExtensionType.EXT_STATUS_REQUEST_V2) {
extension = new CertStatusReqListV2Extension(s, extlen);
+ } else if (extType == ExtensionType.EXT_EXTENDED_MASTER_SECRET) {
+ extension = new ExtendedMasterSecretExtension(s, extlen);
} else {
extension = new UnknownExtension(s, extlen, extType);
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java
--- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,7 @@
private byte compressionMethod;
private CipherSuite cipherSuite;
private SecretKey masterSecret;
+ private final boolean useExtendedMasterSecret;
/*
* Information not part of the SSLv3 protocol spec, but used
@@ -148,7 +149,7 @@
*/
private SSLSessionImpl() {
this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
- new SessionId(false, null), null, -1);
+ new SessionId(false, null), null, -1, false);
}
/*
@@ -158,9 +159,11 @@
*/
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection algorithms,
- SecureRandom generator, String host, int port) {
+ SecureRandom generator, String host, int port,
+ boolean useExtendedMasterSecret) {
this(protocolVersion, cipherSuite, algorithms,
- new SessionId(defaultRejoinable, generator), host, port);
+ new SessionId(defaultRejoinable, generator), host, port,
+ useExtendedMasterSecret);
}
/*
@@ -168,7 +171,8 @@
*/
SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
Collection algorithms,
- SessionId id, String host, int port) {
+ SessionId id, String host, int port,
+ boolean useExtendedMasterSecret) {
this.protocolVersion = protocolVersion;
sessionId = id;
peerCerts = null;
@@ -182,6 +186,7 @@
SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
negotiatedMaxFragLen = -1;
statusResponses = null;
+ this.useExtendedMasterSecret = useExtendedMasterSecret;
if (debug != null && Debug.isOn("session")) {
System.out.println("%% Initialized: " + this);
@@ -203,6 +208,10 @@
return masterSecret;
}
+ boolean getUseExtendedMasterSecret() {
+ return useExtendedMasterSecret;
+ }
+
void setPeerCertificates(X509Certificate[] peer) {
if (peerCerts == null) {
peerCerts = peer;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java
--- a/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java Thu Dec 14 12:28:32 2017 +0000
@@ -529,6 +529,27 @@
}
}
+ // check out the "extended_master_secret" extension
+ if (useExtendedMasterSecret) {
+ ExtendedMasterSecretExtension extendedMasterSecretExtension =
+ (ExtendedMasterSecretExtension)mesg.extensions.get(
+ ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+ if (extendedMasterSecretExtension != null) {
+ requestedToUseEMS = true;
+ } else if (mesg.protocolVersion.useTLS10PlusSpec()) {
+ if (!allowLegacyMasterSecret) {
+ // For full handshake, if the server receives a ClientHello
+ // without the extension, it SHOULD abort the handshake if
+ // it does not wish to interoperate with legacy clients.
+ //
+ // As if extended master extension is required for full
+ // handshake, it MUST be used in abbreviated handshake too.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Extended Master Secret extension is required");
+ }
+ }
+ }
+
// check the ALPN extension
ALPNExtension clientHelloALPN = (ALPNExtension)
mesg.extensions.get(ExtensionType.EXT_ALPN);
@@ -592,8 +613,42 @@
if (resumingSession) {
ProtocolVersion oldVersion = previous.getProtocolVersion();
// cannot resume session with different version
- if (oldVersion != protocolVersion) {
+ if (oldVersion != mesg.protocolVersion) {
+ resumingSession = false;
+ }
+ }
+
+ if (resumingSession && useExtendedMasterSecret) {
+ if (requestedToUseEMS &&
+ !previous.getUseExtendedMasterSecret()) {
+ // For abbreviated handshake request, If the original
+ // session did not use the "extended_master_secret"
+ // extension but the new ClientHello contains the
+ // extension, then the server MUST NOT perform the
+ // abbreviated handshake. Instead, it SHOULD continue
+ // with a full handshake.
resumingSession = false;
+ } else if (!requestedToUseEMS &&
+ previous.getUseExtendedMasterSecret()) {
+ // For abbreviated handshake request, if the original
+ // session used the "extended_master_secret" extension
+ // but the new ClientHello does not contain it, the
+ // server MUST abort the abbreviated handshake.
+ fatalSE(Alerts.alert_handshake_failure,
+ "Missing Extended Master Secret extension " +
+ "on session resumption");
+ } else if (!requestedToUseEMS &&
+ !previous.getUseExtendedMasterSecret()) {
+ // For abbreviated handshake request, if neither the
+ // original session nor the new ClientHello uses the
+ // extension, the server SHOULD abort the handshake.
+ if (!allowLegacyResumption) {
+ fatalSE(Alerts.alert_handshake_failure,
+ "Missing Extended Master Secret extension " +
+ "on session resumption");
+ } else { // Otherwise, continue with a full handshake.
+ resumingSession = false;
+ }
}
}
@@ -630,7 +685,7 @@
if (resumingSession) {
CipherSuite suite = previous.getSuite();
ClientKeyExchangeService p =
- ClientKeyExchangeService.find(suite.keyExchange.name);
+ ClientKeyExchangeService.find(suite.keyExchange.name);
if (p != null) {
Principal localPrincipal = previous.getLocalPrincipal();
@@ -784,7 +839,9 @@
session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
getLocalSupportedSignAlgs(),
sslContext.getSecureRandom(),
- getHostAddressSE(), getPortSE());
+ getHostAddressSE(), getPortSE(),
+ (requestedToUseEMS &&
+ protocolVersion.useTLS10PlusSpec()));
if (protocolVersion.useTLS12PlusSpec()) {
if (peerSupportedSignAlgs != null) {
@@ -886,6 +943,10 @@
m1.extensions.add(maxFragLenExt);
}
+ if (session.getUseExtendedMasterSecret()) {
+ m1.extensions.add(new ExtendedMasterSecretExtension());
+ }
+
StaplingParameters staplingParams = processStapling(mesg);
if (staplingParams != null) {
// We now can safely assert status_request[_v2] in our
@@ -963,7 +1024,8 @@
* defined in the protocol spec are explicitly stated to require
* using RSA certificates.
*/
- if (ClientKeyExchangeService.find(cipherSuite.keyExchange.name) != null) {
+ if (ClientKeyExchangeService.find(
+ cipherSuite.keyExchange.name) != null) {
// No external key exchange provider needs a cert now.
} else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
if (certs == null) {
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java
--- a/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/tools/KeyStoreUtil.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -93,8 +93,9 @@
* MSCAPI KeyStores
*/
public static boolean isWindowsKeyStore(String storetype) {
- return storetype.equalsIgnoreCase("Windows-MY")
- || storetype.equalsIgnoreCase("Windows-ROOT");
+ return storetype != null
+ && (storetype.equalsIgnoreCase("Windows-MY")
+ || storetype.equalsIgnoreCase("Windows-ROOT"));
}
/**
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/security/tools/keytool/Main.java
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java Thu Dec 14 12:28:32 2017 +0000
@@ -134,8 +134,6 @@
private Set> providers = null;
private Set> providerClasses = null;
private String storetype = null;
- private boolean hasStoretypeOption = false;
- private boolean hasSrcStoretypeOption = false;
private String srcProviderName = null;
private String providerName = null;
private String pathlist = null;
@@ -549,14 +547,12 @@
passwords.add(storePass);
} else if (collator.compare(flags, "-storetype") == 0 ||
collator.compare(flags, "-deststoretype") == 0) {
- storetype = args[++i];
- hasStoretypeOption = true;
+ storetype = KeyStoreUtil.niceStoreTypeName(args[++i]);
} else if (collator.compare(flags, "-srcstorepass") == 0) {
srcstorePass = getPass(modifier, args[++i]);
passwords.add(srcstorePass);
} else if (collator.compare(flags, "-srcstoretype") == 0) {
- srcstoretype = args[++i];
- hasSrcStoretypeOption = true;
+ srcstoretype = KeyStoreUtil.niceStoreTypeName(args[++i]);
} else if (collator.compare(flags, "-srckeypass") == 0) {
srckeyPass = getPass(modifier, args[++i]);
passwords.add(srckeyPass);
@@ -708,16 +704,6 @@
ksfname = KeyStoreUtil.getCacerts();
}
- if (storetype == null) {
- storetype = KeyStore.getDefaultType();
- }
- storetype = KeyStoreUtil.niceStoreTypeName(storetype);
-
- if (srcstoretype == null) {
- srcstoretype = KeyStore.getDefaultType();
- }
- srcstoretype = KeyStoreUtil.niceStoreTypeName(srcstoretype);
-
if (P11KEYSTORE.equalsIgnoreCase(storetype) ||
KeyStoreUtil.isWindowsKeyStore(storetype)) {
token = true;
@@ -742,11 +728,6 @@
(".storepasswd.and.keypasswd.commands.not.supported.if.storetype.is.{0}"), storetype));
}
- if (P12KEYSTORE.equalsIgnoreCase(storetype) && command == KEYPASSWD) {
- throw new UnsupportedOperationException(rb.getString
- (".keypasswd.commands.not.supported.if.storetype.is.PKCS12"));
- }
-
if (token && (keyPass != null || newPass != null || destKeyPass != null)) {
throw new IllegalArgumentException(MessageFormat.format(rb.getString
(".keypass.and.new.can.not.be.specified.if.storetype.is.{0}"), storetype));
@@ -923,9 +904,13 @@
// Create new keystore
// Probe for keystore type when filename is available
if (ksfile != null && ksStream != null && providerName == null &&
- hasStoretypeOption == false && !inplaceImport) {
+ storetype == null && !inplaceImport) {
keyStore = KeyStore.getInstance(ksfile, storePass);
+ storetype = keyStore.getType();
} else {
+ if (storetype == null) {
+ storetype = KeyStore.getDefaultType();
+ }
if (providerName == null) {
keyStore = KeyStore.getInstance(storetype);
} else {
@@ -964,6 +949,11 @@
}
}
+ if (P12KEYSTORE.equalsIgnoreCase(storetype) && command == KEYPASSWD) {
+ throw new UnsupportedOperationException(rb.getString
+ (".keypasswd.commands.not.supported.if.storetype.is.PKCS12"));
+ }
+
// All commands that create or modify the keystore require a keystore
// password.
@@ -2123,9 +2113,13 @@
try {
// Probe for keystore type when filename is available
if (srcksfile != null && is != null && srcProviderName == null &&
- hasSrcStoretypeOption == false) {
+ srcstoretype == null) {
store = KeyStore.getInstance(srcksfile, srcstorePass);
+ srcstoretype = store.getType();
} else {
+ if (srcstoretype == null) {
+ srcstoretype = KeyStore.getDefaultType();
+ }
if (srcProviderName == null) {
store = KeyStore.getInstance(srcstoretype);
} else {
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/cldr/CLDRCalendarDataProviderImpl.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/util/cldr/CLDRCalendarDataProviderImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.util.cldr;
+
+import static sun.util.locale.provider.LocaleProviderAdapter.Type;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Locale;
+import java.util.Set;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import sun.util.locale.provider.LocaleProviderAdapter;
+import sun.util.locale.provider.LocaleResources;
+import sun.util.locale.provider.CalendarDataProviderImpl;
+import sun.util.locale.provider.CalendarDataUtility;
+
+/**
+ * Concrete implementation of the
+ * {@link java.util.spi.CalendarDataProvider CalendarDataProvider} class
+ * for the CLDR LocaleProviderAdapter.
+ *
+ * @author Naoto Sato
+ */
+public class CLDRCalendarDataProviderImpl extends CalendarDataProviderImpl {
+
+ private static Map firstDay = new ConcurrentHashMap<>();
+ private static Map minDays = new ConcurrentHashMap<>();
+
+ public CLDRCalendarDataProviderImpl(Type type, Set langtags) {
+ super(type, langtags);
+ }
+
+ @Override
+ public int getFirstDayOfWeek(Locale locale) {
+ return findValue(CalendarDataUtility.FIRST_DAY_OF_WEEK, locale);
+ }
+
+ @Override
+ public int getMinimalDaysInFirstWeek(Locale locale) {
+ return findValue(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK, locale);
+ }
+
+ /**
+ * Finds the requested integer value for the locale.
+ * Each resource consists of the following:
+ *
+ * (n: cc1 cc2 ... ccx;)*
+ *
+ * where 'n' is the integer for the following region codes, terminated by
+ * a ';'.
+ *
+ */
+ private static int findValue(String key, Locale locale) {
+ Map map = CalendarDataUtility.FIRST_DAY_OF_WEEK.equals(key) ?
+ firstDay : minDays;
+ String region = locale.getCountry();
+
+ if (region.isEmpty()) {
+ return 0;
+ }
+
+ Integer val = map.get(region);
+ if (val == null) {
+ String valStr =
+ LocaleProviderAdapter.forType(Type.CLDR).getLocaleResources(Locale.ROOT)
+ .getCalendarData(key);
+ val = retrieveInteger(valStr, region)
+ .orElse(retrieveInteger(valStr, "001").orElse(0));
+ map.putIfAbsent(region, val);
+ }
+
+ return val;
+ }
+
+ private static Optional retrieveInteger(String src, String region) {
+ return Arrays.stream(src.split(";"))
+ .filter(entry -> entry.contains(region))
+ .map(entry -> entry.substring(0, entry.indexOf(":")))
+ .findAny()
+ .map(Integer::parseInt);
+ }
+}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java
--- a/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java Thu Dec 14 12:28:32 2017 +0000
@@ -27,6 +27,7 @@
import java.security.AccessController;
import java.security.AccessControlException;
+import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.spi.BreakIteratorProvider;
@@ -37,15 +38,16 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.Objects;
+import java.util.Optional;
import java.util.ServiceLoader;
import java.util.ServiceConfigurationError;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.spi.CalendarDataProvider;
import sun.util.locale.provider.JRELocaleProviderAdapter;
+import sun.util.locale.provider.LocaleDataMetaInfo;
import sun.util.locale.provider.LocaleProviderAdapter;
-import sun.util.locale.provider.LocaleDataMetaInfo;
/**
* LocaleProviderAdapter implementation for the CLDR locale data.
@@ -106,6 +108,24 @@
}
@Override
+ public CalendarDataProvider getCalendarDataProvider() {
+ if (calendarDataProvider == null) {
+ CalendarDataProvider provider = AccessController.doPrivileged(
+ (PrivilegedAction) () ->
+ new CLDRCalendarDataProviderImpl(
+ getAdapterType(),
+ getLanguageTagSet("CalendarData")));
+
+ synchronized (this) {
+ if (calendarDataProvider == null) {
+ calendarDataProvider = provider;
+ }
+ }
+ }
+ return calendarDataProvider;
+ }
+
+ @Override
public CollatorProvider getCollatorProvider() {
return null;
}
@@ -123,6 +143,10 @@
@Override
protected Set createLanguageTagSet(String category) {
+ // Assume all categories support the same set as AvailableLocales
+ // in CLDR adapter.
+ category = "AvailableLocales";
+
// Directly call Base tags, as we know it's in the base module.
String supportedLocaleString = baseMetaInfo.availableLanguageTags(category);
String nonBaseTags = null;
@@ -220,4 +244,11 @@
|| langtags.contains(locale.stripExtensions().toLanguageTag())
|| langtags.contains(getEquivalentLoc(locale).toLanguageTag());
}
+
+ /**
+ * Returns the time zone ID from an LDML's short ID
+ */
+ public Optional getTimeZoneID(String shortID) {
+ return Optional.ofNullable(baseMetaInfo.tzShortIDs().get(shortID));
+ }
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java
--- a/src/java.base/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/CalendarDataProviderImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,14 +46,16 @@
@Override
public int getFirstDayOfWeek(Locale locale) {
- return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
+ String fw = LocaleProviderAdapter.forType(type).getLocaleResources(locale)
.getCalendarData(CalendarDataUtility.FIRST_DAY_OF_WEEK);
+ return convertToCalendarData(fw);
}
@Override
public int getMinimalDaysInFirstWeek(Locale locale) {
- return LocaleProviderAdapter.forType(type).getLocaleResources(locale)
+ String md = LocaleProviderAdapter.forType(type).getLocaleResources(locale)
.getCalendarData(CalendarDataUtility.MINIMAL_DAYS_IN_FIRST_WEEK);
+ return convertToCalendarData(md);
}
@Override
@@ -65,4 +67,9 @@
public Set getAvailableLanguageTags() {
return langtags;
}
+
+ private int convertToCalendarData(String src) {
+ int val = Integer.parseInt(src);
+ return (src.isEmpty() || val <= 0 || val > 7) ? 0 : val;
+ }
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java
--- a/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/CalendarDataUtility.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,10 +47,34 @@
}
public static int retrieveFirstDayOfWeek(Locale locale) {
+ // Look for the Unicode Extension in the locale parameter
+ if (locale.hasExtensions()) {
+ String fw = locale.getUnicodeLocaleType("fw");
+ if (fw != null) {
+ switch (fw.toLowerCase(Locale.ROOT)) {
+ case "mon":
+ return MONDAY;
+ case "tue":
+ return TUESDAY;
+ case "wed":
+ return WEDNESDAY;
+ case "thu":
+ return THURSDAY;
+ case "fri":
+ return FRIDAY;
+ case "sat":
+ return SATURDAY;
+ case "sun":
+ return SUNDAY;
+ }
+ }
+ }
+
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
- locale, true, FIRST_DAY_OF_WEEK);
+ findRegionOverride(locale),
+ true, FIRST_DAY_OF_WEEK);
return (value != null && (value >= SUNDAY && value <= SATURDAY)) ? value : SUNDAY;
}
@@ -58,7 +82,8 @@
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(CalendarDataProvider.class);
Integer value = pool.getLocalizedObject(CalendarWeekParameterGetter.INSTANCE,
- locale, true, MINIMAL_DAYS_IN_FIRST_WEEK);
+ findRegionOverride(locale),
+ true, MINIMAL_DAYS_IN_FIRST_WEEK);
return (value != null && (value >= 1 && value <= 7)) ? value : 1;
}
@@ -102,6 +127,32 @@
return map;
}
+ /**
+ * Utility to look for a region override extension.
+ * If no region override is found, returns the original locale.
+ */
+ public static Locale findRegionOverride(Locale l) {
+ String rg = l.getUnicodeLocaleType("rg");
+ Locale override = l;
+
+ if (rg != null && rg.length() == 6) {
+ // UN M.49 code should not be allowed here
+ // cannot use regex here, as it could be a recursive call
+ rg = rg.toUpperCase(Locale.ROOT);
+ if (rg.charAt(0) >= 0x0041 &&
+ rg.charAt(0) <= 0x005A &&
+ rg.charAt(1) >= 0x0041 &&
+ rg.charAt(1) <= 0x005A &&
+ rg.substring(2).equals("ZZZZ")) {
+ override = new Locale.Builder().setLocale(l)
+ .setRegion(rg.substring(0, 2))
+ .build();
+ }
+ }
+
+ return override;
+ }
+
static String normalizeCalendarType(String requestID) {
String type;
if (requestID.equals("gregorian") || requestID.equals("iso8601")) {
@@ -179,7 +230,7 @@
}
}
- private static class CalendarWeekParameterGetter
+ private static class CalendarWeekParameterGetter
implements LocaleServiceProviderPool.LocalizedObjectGetter {
private static final CalendarWeekParameterGetter INSTANCE =
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/DateFormatProviderImpl.java
--- a/src/java.base/share/classes/sun/util/locale/provider/DateFormatProviderImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/DateFormatProviderImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,6 +32,7 @@
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.Set;
+import java.util.TimeZone;
/**
* Concrete implementation of the {@link java.text.spi.DateFormatProvider
@@ -147,11 +148,14 @@
throw new NullPointerException();
}
- SimpleDateFormat sdf = new SimpleDateFormat("", locale);
+ // Check for region override
+ Locale rg = CalendarDataUtility.findRegionOverride(locale);
+
+ SimpleDateFormat sdf = new SimpleDateFormat("", rg);
Calendar cal = sdf.getCalendar();
try {
String pattern = LocaleProviderAdapter.forType(type)
- .getLocaleResources(locale).getDateTimePattern(timeStyle, dateStyle,
+ .getLocaleResources(rg).getDateTimePattern(timeStyle, dateStyle,
cal);
sdf.applyPattern(pattern);
} catch (MissingResourceException mre) {
@@ -159,6 +163,15 @@
sdf.applyPattern("M/d/yy h:mm a");
}
+ // Check for timezone override
+ String tz = locale.getUnicodeLocaleType("tz");
+ if (tz != null) {
+ sdf.setTimeZone(
+ TimeZoneNameUtility.convertLDMLShortID(tz)
+ .map(TimeZone::getTimeZone)
+ .orElseGet(sdf::getTimeZone));
+ }
+
return sdf;
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java
--- a/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -130,7 +130,7 @@
private volatile CurrencyNameProvider currencyNameProvider;
private volatile LocaleNameProvider localeNameProvider;
private volatile TimeZoneNameProvider timeZoneNameProvider;
- private volatile CalendarDataProvider calendarDataProvider;
+ protected volatile CalendarDataProvider calendarDataProvider;
private volatile CalendarNameProvider calendarNameProvider;
private volatile CalendarProvider calendarProvider;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* 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 sun.util.locale.provider;
+import java.util.Map;
+
/**
* LocaleData meta info SPI
*
@@ -46,4 +48,13 @@
* @return concatenated language tags, separated by a space.
*/
public String availableLanguageTags(String category);
+
+ /**
+ * Returns a map for short time zone ids in BCP47 Unicode extension and
+ * the long time zone ids.
+ * @return map of short id to long ids, separated by a space.
+ */
+ default public Map tzShortIDs() {
+ return null;
+ }
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleNameProviderImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -168,6 +168,28 @@
return getDisplayString("%%"+vrnt, locale);
}
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
+ super.getDisplayUnicodeExtensionKey(key, locale); // null check
+ String rbKey = "key." + key;
+ String name = getDisplayString(rbKey, locale);
+ return rbKey.equals(name) ? key : name;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public String getDisplayUnicodeExtensionType(String extType, String key, Locale locale) {
+ super.getDisplayUnicodeExtensionType(extType, key, locale); // null check
+ String rbKey = "type." + key + "." + extType;
+ String name = getDisplayString(rbKey, locale);
+ return rbKey.equals(name) ? extType : name;
+ }
+
private String getDisplayString(String key, Locale locale) {
if (key == null || locale == null) {
throw new NullPointerException();
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java
--- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -122,23 +122,21 @@
return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
}
- int getCalendarData(String key) {
- Integer caldata;
+ public String getCalendarData(String key) {
+ String caldata = "";
String cacheKey = CALENDAR_DATA + key;
removeEmptyReferences();
ResourceReference data = cache.get(cacheKey);
- if (data == null || ((caldata = (Integer) data.get()) == null)) {
+ if (data == null || ((caldata = (String) data.get()) == null)) {
ResourceBundle rb = localeData.getCalendarData(locale);
if (rb.containsKey(key)) {
- caldata = Integer.parseInt(rb.getString(key));
- } else {
- caldata = 0;
+ caldata = rb.getString(key);
}
cache.put(cacheKey,
- new ResourceReference(cacheKey, (Object) caldata, referenceQueue));
+ new ResourceReference(cacheKey, caldata, referenceQueue));
}
return caldata;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/NumberFormatProviderImpl.java
--- a/src/java.base/share/classes/sun/util/locale/provider/NumberFormatProviderImpl.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/NumberFormatProviderImpl.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -173,9 +173,14 @@
throw new NullPointerException();
}
+ // Check for region override
+ Locale override = locale.getUnicodeLocaleType("nu") == null ?
+ CalendarDataUtility.findRegionOverride(locale) :
+ locale;
+
LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type);
- String[] numberPatterns = adapter.getLocaleResources(locale).getNumberPatterns();
- DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(locale);
+ String[] numberPatterns = adapter.getLocaleResources(override).getNumberPatterns();
+ DecimalFormatSymbols symbols = DecimalFormatSymbols.getInstance(override);
int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
DecimalFormat format = new DecimalFormat(numberPatterns[entry], symbols);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java
--- a/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/SPILocaleProviderAdapter.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -160,28 +160,24 @@
@Override
public BreakIterator getWordInstance(Locale locale) {
BreakIteratorProvider bip = getImpl(locale);
- assert bip != null;
return bip.getWordInstance(locale);
}
@Override
public BreakIterator getLineInstance(Locale locale) {
BreakIteratorProvider bip = getImpl(locale);
- assert bip != null;
return bip.getLineInstance(locale);
}
@Override
public BreakIterator getCharacterInstance(Locale locale) {
BreakIteratorProvider bip = getImpl(locale);
- assert bip != null;
return bip.getCharacterInstance(locale);
}
@Override
public BreakIterator getSentenceInstance(Locale locale) {
BreakIteratorProvider bip = getImpl(locale);
- assert bip != null;
return bip.getSentenceInstance(locale);
}
@@ -215,7 +211,6 @@
@Override
public Collator getInstance(Locale locale) {
CollatorProvider cp = getImpl(locale);
- assert cp != null;
return cp.getInstance(locale);
}
}
@@ -249,21 +244,18 @@
@Override
public DateFormat getTimeInstance(int style, Locale locale) {
DateFormatProvider dfp = getImpl(locale);
- assert dfp != null;
return dfp.getTimeInstance(style, locale);
}
@Override
public DateFormat getDateInstance(int style, Locale locale) {
DateFormatProvider dfp = getImpl(locale);
- assert dfp != null;
return dfp.getDateInstance(style, locale);
}
@Override
public DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) {
DateFormatProvider dfp = getImpl(locale);
- assert dfp != null;
return dfp.getDateTimeInstance(dateStyle, timeStyle, locale);
}
}
@@ -297,7 +289,6 @@
@Override
public DateFormatSymbols getInstance(Locale locale) {
DateFormatSymbolsProvider dfsp = getImpl(locale);
- assert dfsp != null;
return dfsp.getInstance(locale);
}
}
@@ -331,7 +322,6 @@
@Override
public DecimalFormatSymbols getInstance(Locale locale) {
DecimalFormatSymbolsProvider dfsp = getImpl(locale);
- assert dfsp != null;
return dfsp.getInstance(locale);
}
}
@@ -365,28 +355,24 @@
@Override
public NumberFormat getCurrencyInstance(Locale locale) {
NumberFormatProvider nfp = getImpl(locale);
- assert nfp != null;
return nfp.getCurrencyInstance(locale);
}
@Override
public NumberFormat getIntegerInstance(Locale locale) {
NumberFormatProvider nfp = getImpl(locale);
- assert nfp != null;
return nfp.getIntegerInstance(locale);
}
@Override
public NumberFormat getNumberInstance(Locale locale) {
NumberFormatProvider nfp = getImpl(locale);
- assert nfp != null;
return nfp.getNumberInstance(locale);
}
@Override
public NumberFormat getPercentInstance(Locale locale) {
NumberFormatProvider nfp = getImpl(locale);
- assert nfp != null;
return nfp.getPercentInstance(locale);
}
}
@@ -420,14 +406,12 @@
@Override
public int getFirstDayOfWeek(Locale locale) {
CalendarDataProvider cdp = getImpl(locale);
- assert cdp != null;
return cdp.getFirstDayOfWeek(locale);
}
@Override
public int getMinimalDaysInFirstWeek(Locale locale) {
CalendarDataProvider cdp = getImpl(locale);
- assert cdp != null;
return cdp.getMinimalDaysInFirstWeek(locale);
}
}
@@ -463,7 +447,6 @@
int field, int value,
int style, Locale locale) {
CalendarNameProvider cdp = getImpl(locale);
- assert cdp != null;
return cdp.getDisplayName(calendarType, field, value, style, locale);
}
@@ -472,7 +455,6 @@
int field, int style,
Locale locale) {
CalendarNameProvider cdp = getImpl(locale);
- assert cdp != null;
return cdp.getDisplayNames(calendarType, field, style, locale);
}
}
@@ -506,14 +488,12 @@
@Override
public String getSymbol(String currencyCode, Locale locale) {
CurrencyNameProvider cnp = getImpl(locale);
- assert cnp != null;
return cnp.getSymbol(currencyCode, locale);
}
@Override
public String getDisplayName(String currencyCode, Locale locale) {
CurrencyNameProvider cnp = getImpl(locale);
- assert cnp != null;
return cnp.getDisplayName(currencyCode, locale);
}
}
@@ -547,30 +527,38 @@
@Override
public String getDisplayLanguage(String languageCode, Locale locale) {
LocaleNameProvider lnp = getImpl(locale);
- assert lnp != null;
return lnp.getDisplayLanguage(languageCode, locale);
}
@Override
public String getDisplayScript(String scriptCode, Locale locale) {
LocaleNameProvider lnp = getImpl(locale);
- assert lnp != null;
return lnp.getDisplayScript(scriptCode, locale);
}
@Override
public String getDisplayCountry(String countryCode, Locale locale) {
LocaleNameProvider lnp = getImpl(locale);
- assert lnp != null;
return lnp.getDisplayCountry(countryCode, locale);
}
@Override
public String getDisplayVariant(String variant, Locale locale) {
LocaleNameProvider lnp = getImpl(locale);
- assert lnp != null;
return lnp.getDisplayVariant(variant, locale);
}
+
+ @Override
+ public String getDisplayUnicodeExtensionKey(String key, Locale locale) {
+ LocaleNameProvider lnp = getImpl(locale);
+ return lnp.getDisplayUnicodeExtensionKey(key, locale);
+ }
+
+ @Override
+ public String getDisplayUnicodeExtensionType(String extType, String key, Locale locale) {
+ LocaleNameProvider lnp = getImpl(locale);
+ return lnp.getDisplayUnicodeExtensionType(extType, key, locale);
+ }
}
static class TimeZoneNameProviderDelegate extends TimeZoneNameProvider
@@ -602,14 +590,12 @@
@Override
public String getDisplayName(String ID, boolean daylight, int style, Locale locale) {
TimeZoneNameProvider tznp = getImpl(locale);
- assert tznp != null;
return tznp.getDisplayName(ID, daylight, style, locale);
}
@Override
public String getGenericDisplayName(String ID, int style, Locale locale) {
TimeZoneNameProvider tznp = getImpl(locale);
- assert tznp != null;
return tznp.getGenericDisplayName(ID, style, locale);
}
}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameUtility.java
--- a/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameUtility.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/locale/provider/TimeZoneNameUtility.java Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* 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,10 +31,13 @@
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.spi.TimeZoneNameProvider;
import sun.util.calendar.ZoneInfo;
+import sun.util.cldr.CLDRLocaleProviderAdapter;
+import static sun.util.locale.provider.LocaleProviderAdapter.Type;
/**
* Utility class that deals with the localized time zone names
@@ -152,6 +155,18 @@
}
}
+ /**
+ * Converts the time zone id from LDML's 5-letter id to tzdb's id
+ *
+ * @param shortID time zone short ID defined in LDML
+ * @return the tzdb's time zone ID
+ */
+ public static Optional convertLDMLShortID(String shortID) {
+ return ((CLDRLocaleProviderAdapter)LocaleProviderAdapter.forType(Type.CLDR))
+ .getTimeZoneID(shortID)
+ .map(id -> id.replaceAll("\\s.*", ""));
+ }
+
private static String[] retrieveDisplayNamesImpl(String id, Locale locale) {
LocaleServiceProviderPool pool =
LocaleServiceProviderPool.getPool(TimeZoneNameProvider.class);
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/classes/sun/util/resources/LocaleNames.properties
--- a/src/java.base/share/classes/sun/util/resources/LocaleNames.properties Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/classes/sun/util/resources/LocaleNames.properties Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -1164,8 +1164,7 @@
# locale name patterns
-# rarely localized
DisplayNamePattern={0,choice,0#|1#{1}|2#{1} ({2})}
-ListPattern={0,choice,0#|1#{1}|2#{1},{2}|3#{1},{2},{3}}
+ListKeyTypePattern={0}:{1}
ListCompositionPattern={0},{1}
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/lib/security/cacerts
Binary file src/java.base/share/lib/security/cacerts has changed
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/native/include/jvm.h
--- a/src/java.base/share/native/include/jvm.h Mon Dec 11 16:43:11 2017 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1328 +0,0 @@
-/*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-#ifndef _JAVASOFT_JVM_H_
-#define _JAVASOFT_JVM_H_
-
-#include
-
-#include "jni.h"
-#include "jvm_md.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * This file contains additional functions exported from the VM.
- * These functions are complementary to the standard JNI support.
- * There are three parts to this file:
- *
- * First, this file contains the VM-related functions needed by native
- * libraries in the standard Java API. For example, the java.lang.Object
- * class needs VM-level functions that wait for and notify monitors.
- *
- * Second, this file contains the functions and constant definitions
- * needed by the byte code verifier and class file format checker.
- * These functions allow the verifier and format checker to be written
- * in a VM-independent way.
- *
- * Third, this file contains various I/O and network operations needed
- * by the standard Java I/O and network APIs.
- */
-
-/*
- * Bump the version number when either of the following happens:
- *
- * 1. There is a change in JVM_* functions.
- *
- * 2. There is a change in the contract between VM and Java classes.
- * For example, if the VM relies on a new private field in Thread
- * class.
- */
-
-#define JVM_INTERFACE_VERSION 5
-
-JNIEXPORT jint JNICALL
-JVM_GetInterfaceVersion(void);
-
-/*************************************************************************
- PART 1: Functions for Native Libraries
- ************************************************************************/
-/*
- * java.lang.Object
- */
-JNIEXPORT jint JNICALL
-JVM_IHashCode(JNIEnv *env, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_MonitorWait(JNIEnv *env, jobject obj, jlong ms);
-
-JNIEXPORT void JNICALL
-JVM_MonitorNotify(JNIEnv *env, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_MonitorNotifyAll(JNIEnv *env, jobject obj);
-
-JNIEXPORT jobject JNICALL
-JVM_Clone(JNIEnv *env, jobject obj);
-
-/*
- * java.lang.String
- */
-JNIEXPORT jstring JNICALL
-JVM_InternString(JNIEnv *env, jstring str);
-
-/*
- * java.lang.System
- */
-JNIEXPORT jlong JNICALL
-JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored);
-
-JNIEXPORT jlong JNICALL
-JVM_NanoTime(JNIEnv *env, jclass ignored);
-
-JNIEXPORT jlong JNICALL
-JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs);
-
-JNIEXPORT void JNICALL
-JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
- jobject dst, jint dst_pos, jint length);
-
-JNIEXPORT jobject JNICALL
-JVM_InitProperties(JNIEnv *env, jobject p);
-
-
-/*
- * java.lang.Runtime
- */
-JNIEXPORT void JNICALL
-JVM_Halt(jint code);
-
-JNIEXPORT void JNICALL
-JVM_GC(void);
-
-/* Returns the number of real-time milliseconds that have elapsed since the
- * least-recently-inspected heap object was last inspected by the garbage
- * collector.
- *
- * For simple stop-the-world collectors this value is just the time
- * since the most recent collection. For generational collectors it is the
- * time since the oldest generation was most recently collected. Other
- * collectors are free to return a pessimistic estimate of the elapsed time, or
- * simply the time since the last full collection was performed.
- *
- * Note that in the presence of reference objects, a given object that is no
- * longer strongly reachable may have to be inspected multiple times before it
- * can be reclaimed.
- */
-JNIEXPORT jlong JNICALL
-JVM_MaxObjectInspectionAge(void);
-
-JNIEXPORT jlong JNICALL
-JVM_TotalMemory(void);
-
-JNIEXPORT jlong JNICALL
-JVM_FreeMemory(void);
-
-JNIEXPORT jlong JNICALL
-JVM_MaxMemory(void);
-
-JNIEXPORT jint JNICALL
-JVM_ActiveProcessorCount(void);
-
-JNIEXPORT void * JNICALL
-JVM_LoadLibrary(const char *name);
-
-JNIEXPORT void JNICALL
-JVM_UnloadLibrary(void * handle);
-
-JNIEXPORT void * JNICALL
-JVM_FindLibraryEntry(void *handle, const char *name);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsSupportedJNIVersion(jint version);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetVmArguments(JNIEnv *env);
-
-
-/*
- * java.lang.Throwable
- */
-JNIEXPORT void JNICALL
-JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
-
-/*
- * java.lang.StackTraceElement
- */
-JNIEXPORT void JNICALL
-JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable);
-
-JNIEXPORT void JNICALL
-JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo);
-
-/*
- * java.lang.StackWalker
- */
-enum {
- JVM_STACKWALK_FILL_CLASS_REFS_ONLY = 0x2,
- JVM_STACKWALK_GET_CALLER_CLASS = 0x04,
- JVM_STACKWALK_SHOW_HIDDEN_FRAMES = 0x20,
- JVM_STACKWALK_FILL_LIVE_STACK_FRAMES = 0x100
-};
-
-JNIEXPORT jobject JNICALL
-JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
- jint skip_frames, jint frame_count, jint start_index,
- jobjectArray frames);
-
-JNIEXPORT jint JNICALL
-JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
- jint frame_count, jint start_index,
- jobjectArray frames);
-
-/*
- * java.lang.Thread
- */
-JNIEXPORT void JNICALL
-JVM_StartThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_StopThread(JNIEnv *env, jobject thread, jobject exception);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsThreadAlive(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_SuspendThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_ResumeThread(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_SetThreadPriority(JNIEnv *env, jobject thread, jint prio);
-
-JNIEXPORT void JNICALL
-JVM_Yield(JNIEnv *env, jclass threadClass);
-
-JNIEXPORT void JNICALL
-JVM_Sleep(JNIEnv *env, jclass threadClass, jlong millis);
-
-JNIEXPORT jobject JNICALL
-JVM_CurrentThread(JNIEnv *env, jclass threadClass);
-
-JNIEXPORT jint JNICALL
-JVM_CountStackFrames(JNIEnv *env, jobject thread);
-
-JNIEXPORT void JNICALL
-JVM_Interrupt(JNIEnv *env, jobject thread);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsInterrupted(JNIEnv *env, jobject thread, jboolean clearInterrupted);
-
-JNIEXPORT jboolean JNICALL
-JVM_HoldsLock(JNIEnv *env, jclass threadClass, jobject obj);
-
-JNIEXPORT void JNICALL
-JVM_DumpAllStacks(JNIEnv *env, jclass unused);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetAllThreads(JNIEnv *env, jclass dummy);
-
-JNIEXPORT void JNICALL
-JVM_SetNativeThreadName(JNIEnv *env, jobject jthread, jstring name);
-
-/* getStackTrace() and getAllStackTraces() method */
-JNIEXPORT jobjectArray JNICALL
-JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads);
-
-/*
- * java.lang.SecurityManager
- */
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassContext(JNIEnv *env);
-
-/*
- * java.lang.Package
- */
-JNIEXPORT jstring JNICALL
-JVM_GetSystemPackage(JNIEnv *env, jstring name);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetSystemPackages(JNIEnv *env);
-
-/*
- * java.lang.ref.Reference
- */
-JNIEXPORT jobject JNICALL
-JVM_GetAndClearReferencePendingList(JNIEnv *env);
-
-JNIEXPORT jboolean JNICALL
-JVM_HasReferencePendingList(JNIEnv *env);
-
-JNIEXPORT void JNICALL
-JVM_WaitForReferencePendingList(JNIEnv *env);
-
-/*
- * java.io.ObjectInputStream
- */
-JNIEXPORT jobject JNICALL
-JVM_LatestUserDefinedLoader(JNIEnv *env);
-
-/*
- * java.lang.reflect.Array
- */
-JNIEXPORT jint JNICALL
-JVM_GetArrayLength(JNIEnv *env, jobject arr);
-
-JNIEXPORT jobject JNICALL
-JVM_GetArrayElement(JNIEnv *env, jobject arr, jint index);
-
-JNIEXPORT jvalue JNICALL
-JVM_GetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jint wCode);
-
-JNIEXPORT void JNICALL
-JVM_SetArrayElement(JNIEnv *env, jobject arr, jint index, jobject val);
-
-JNIEXPORT void JNICALL
-JVM_SetPrimitiveArrayElement(JNIEnv *env, jobject arr, jint index, jvalue v,
- unsigned char vCode);
-
-JNIEXPORT jobject JNICALL
-JVM_NewArray(JNIEnv *env, jclass eltClass, jint length);
-
-JNIEXPORT jobject JNICALL
-JVM_NewMultiArray(JNIEnv *env, jclass eltClass, jintArray dim);
-
-/*
- * java.lang.Class and java.lang.ClassLoader
- */
-
-#define JVM_CALLER_DEPTH -1
-
-/*
- * Returns the immediate caller class of the native method invoking
- * JVM_GetCallerClass. The Method.invoke and other frames due to
- * reflection machinery are skipped.
- *
- * The depth parameter must be -1 (JVM_DEPTH). The caller is expected
- * to be marked with sun.reflect.CallerSensitive. The JVM will throw
- * an error if it is not marked propertly.
- */
-JNIEXPORT jclass JNICALL
-JVM_GetCallerClass(JNIEnv *env, int depth);
-
-
-/*
- * Find primitive classes
- * utf: class name
- */
-JNIEXPORT jclass JNICALL
-JVM_FindPrimitiveClass(JNIEnv *env, const char *utf);
-
-
-/*
- * Find a class from a boot class loader. Returns NULL if class not found.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
-
-/*
- * Find a class from a given class loader. Throws ClassNotFoundException.
- * name: name of class
- * init: whether initialization is done
- * loader: class loader to look up the class. This may not be the same as the caller's
- * class loader.
- * caller: initiating class. The initiating class may be null when a security
- * manager is not installed.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init,
- jobject loader, jclass caller);
-
-/*
- * Find a class from a given class.
- */
-JNIEXPORT jclass JNICALL
-JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init,
- jclass from);
-
-/* Find a loaded class cached by the VM */
-JNIEXPORT jclass JNICALL
-JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name);
-
-/* Define a class */
-JNIEXPORT jclass JNICALL
-JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf,
- jsize len, jobject pd);
-
-/* Define a class with a source (added in JDK1.5) */
-JNIEXPORT jclass JNICALL
-JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader,
- const jbyte *buf, jsize len, jobject pd,
- const char *source);
-
-/*
- * Module support funcions
- */
-
-/*
- * Define a module with the specified packages and bind the module to the
- * given class loader.
- * module: module to define
- * is_open: specifies if module is open (currently ignored)
- * version: the module version
- * location: the module location
- * packages: list of packages in the module
- * num_packages: number of packages in the module
- */
-JNIEXPORT void JNICALL
-JVM_DefineModule(JNIEnv *env, jobject module, jboolean is_open, jstring version,
- jstring location, const char* const* packages, jsize num_packages);
-
-/*
- * Set the boot loader's unnamed module.
- * module: boot loader's unnamed module
- */
-JNIEXPORT void JNICALL
-JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
-
-/*
- * Do a qualified export of a package.
- * from_module: module containing the package to export
- * package: name of the package to export
- * to_module: module to export the package to
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExports(JNIEnv *env, jobject from_module, const char* package, jobject to_module);
-
-/*
- * Do an export of a package to all unnamed modules.
- * from_module: module containing the package to export
- * package: name of the package to export to all unnamed modules
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, const char* package);
-
-/*
- * Do an unqualified export of a package.
- * from_module: module containing the package to export
- * package: name of the package to export
- */
-JNIEXPORT void JNICALL
-JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, const char* package);
-
-/*
- * Add a module to the list of modules that a given module can read.
- * from_module: module requesting read access
- * source_module: module that from_module wants to read
- */
-JNIEXPORT void JNICALL
-JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
-
-/*
- * Reflection support functions
- */
-
-JNIEXPORT jstring JNICALL
-JVM_GetClassName(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassInterfaces(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsInterface(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassSigners(JNIEnv *env, jclass cls);
-
-JNIEXPORT void JNICALL
-JVM_SetClassSigners(JNIEnv *env, jclass cls, jobjectArray signers);
-
-JNIEXPORT jobject JNICALL
-JVM_GetProtectionDomain(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsArrayClass(JNIEnv *env, jclass cls);
-
-JNIEXPORT jboolean JNICALL
-JVM_IsPrimitiveClass(JNIEnv *env, jclass cls);
-
-JNIEXPORT jint JNICALL
-JVM_GetClassModifiers(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetDeclaredClasses(JNIEnv *env, jclass ofClass);
-
-JNIEXPORT jclass JNICALL
-JVM_GetDeclaringClass(JNIEnv *env, jclass ofClass);
-
-JNIEXPORT jstring JNICALL
-JVM_GetSimpleBinaryName(JNIEnv *env, jclass ofClass);
-
-/* Generics support (JDK 1.5) */
-JNIEXPORT jstring JNICALL
-JVM_GetClassSignature(JNIEnv *env, jclass cls);
-
-/* Annotations support (JDK 1.5) */
-JNIEXPORT jbyteArray JNICALL
-JVM_GetClassAnnotations(JNIEnv *env, jclass cls);
-
-/* Type use annotations support (JDK 1.8) */
-
-JNIEXPORT jbyteArray JNICALL
-JVM_GetClassTypeAnnotations(JNIEnv *env, jclass cls);
-
-JNIEXPORT jbyteArray JNICALL
-JVM_GetFieldTypeAnnotations(JNIEnv *env, jobject field);
-
-JNIEXPORT jbyteArray JNICALL
-JVM_GetMethodTypeAnnotations(JNIEnv *env, jobject method);
-
-/*
- * New (JDK 1.4) reflection implementation
- */
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly);
-
-/* Differs from JVM_GetClassModifiers in treatment of inner classes.
- This returns the access flags for the class as specified in the
- class file rather than searching the InnerClasses attribute (if
- present) to find the source-level access flags. Only the values of
- the low 13 bits (i.e., a mask of 0x1FFF) are guaranteed to be
- valid. */
-JNIEXPORT jint JNICALL
-JVM_GetClassAccessFlags(JNIEnv *env, jclass cls);
-
-/* The following two reflection routines are still needed due to startup time issues */
-/*
- * java.lang.reflect.Method
- */
-JNIEXPORT jobject JNICALL
-JVM_InvokeMethod(JNIEnv *env, jobject method, jobject obj, jobjectArray args0);
-
-/*
- * java.lang.reflect.Constructor
- */
-JNIEXPORT jobject JNICALL
-JVM_NewInstanceFromConstructor(JNIEnv *env, jobject c, jobjectArray args0);
-
-/*
- * Constant pool access; currently used to implement reflective access to annotations (JDK 1.5)
- */
-
-JNIEXPORT jobject JNICALL
-JVM_GetClassConstantPool(JNIEnv *env, jclass cls);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetSize
-(JNIEnv *env, jobject unused, jobject jcpool);
-
-JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jclass JNICALL JVM_ConstantPoolGetClassAtIfLoaded
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetClassRefIndexAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetMethodAtIfLoaded
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jobject JNICALL JVM_ConstantPoolGetFieldAtIfLoaded
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetMemberRefInfoAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetNameAndTypeRefIndexAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jobjectArray JNICALL JVM_ConstantPoolGetNameAndTypeRefInfoAt
-(JNIEnv *env, jobject obj, jobject unused, jint index);
-
-JNIEXPORT jint JNICALL JVM_ConstantPoolGetIntAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jlong JNICALL JVM_ConstantPoolGetLongAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jfloat JNICALL JVM_ConstantPoolGetFloatAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jdouble JNICALL JVM_ConstantPoolGetDoubleAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jstring JNICALL JVM_ConstantPoolGetStringAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jstring JNICALL JVM_ConstantPoolGetUTF8At
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-JNIEXPORT jbyte JNICALL JVM_ConstantPoolGetTagAt
-(JNIEnv *env, jobject unused, jobject jcpool, jint index);
-
-/*
- * Parameter reflection
- */
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetMethodParameters(JNIEnv *env, jobject method);
-
-/*
- * java.security.*
- */
-
-JNIEXPORT jobject JNICALL
-JVM_DoPrivileged(JNIEnv *env, jclass cls,
- jobject action, jobject context, jboolean wrapException);
-
-JNIEXPORT jobject JNICALL
-JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls);
-
-JNIEXPORT jobject JNICALL
-JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls);
-
-/*
- * Signal support, used to implement the shutdown sequence. Every VM must
- * support JVM_SIGINT and JVM_SIGTERM, raising the former for user interrupts
- * (^C) and the latter for external termination (kill, system shutdown, etc.).
- * Other platform-dependent signal values may also be supported.
- */
-
-JNIEXPORT void * JNICALL
-JVM_RegisterSignal(jint sig, void *handler);
-
-JNIEXPORT jboolean JNICALL
-JVM_RaiseSignal(jint sig);
-
-JNIEXPORT jint JNICALL
-JVM_FindSignal(const char *name);
-
-/*
- * Retrieve the assertion directives for the specified class.
- */
-JNIEXPORT jboolean JNICALL
-JVM_DesiredAssertionStatus(JNIEnv *env, jclass unused, jclass cls);
-
-/*
- * Retrieve the assertion directives from the VM.
- */
-JNIEXPORT jobject JNICALL
-JVM_AssertionStatusDirectives(JNIEnv *env, jclass unused);
-
-/*
- * java.util.concurrent.atomic.AtomicLong
- */
-JNIEXPORT jboolean JNICALL
-JVM_SupportsCX8(void);
-
-/*
- * com.sun.dtrace.jsdt support
- */
-
-#define JVM_TRACING_DTRACE_VERSION 1
-
-/*
- * Structure to pass one probe description to JVM
- */
-typedef struct {
- jmethodID method;
- jstring function;
- jstring name;
- void* reserved[4]; // for future use
-} JVM_DTraceProbe;
-
-/**
- * Encapsulates the stability ratings for a DTrace provider field
- */
-typedef struct {
- jint nameStability;
- jint dataStability;
- jint dependencyClass;
-} JVM_DTraceInterfaceAttributes;
-
-/*
- * Structure to pass one provider description to JVM
- */
-typedef struct {
- jstring name;
- JVM_DTraceProbe* probes;
- jint probe_count;
- JVM_DTraceInterfaceAttributes providerAttributes;
- JVM_DTraceInterfaceAttributes moduleAttributes;
- JVM_DTraceInterfaceAttributes functionAttributes;
- JVM_DTraceInterfaceAttributes nameAttributes;
- JVM_DTraceInterfaceAttributes argsAttributes;
- void* reserved[4]; // for future use
-} JVM_DTraceProvider;
-
-/*
- * Get the version number the JVM was built with
- */
-JNIEXPORT jint JNICALL
-JVM_DTraceGetVersion(JNIEnv* env);
-
-/*
- * Register new probe with given signature, return global handle
- *
- * The version passed in is the version that the library code was
- * built with.
- */
-JNIEXPORT jlong JNICALL
-JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name,
- jint providers_count, JVM_DTraceProvider* providers);
-
-/*
- * Check JSDT probe
- */
-JNIEXPORT jboolean JNICALL
-JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method);
-
-/*
- * Destroy custom DOF
- */
-JNIEXPORT void JNICALL
-JVM_DTraceDispose(JNIEnv* env, jlong activation_handle);
-
-/*
- * Check to see if DTrace is supported by OS
- */
-JNIEXPORT jboolean JNICALL
-JVM_DTraceIsSupported(JNIEnv* env);
-
-/*************************************************************************
- PART 2: Support for the Verifier and Class File Format Checker
- ************************************************************************/
-/*
- * Return the class name in UTF format. The result is valid
- * until JVM_ReleaseUTf is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetClassNameUTF(JNIEnv *env, jclass cb);
-
-/*
- * Returns the constant pool types in the buffer provided by "types."
- */
-JNIEXPORT void JNICALL
-JVM_GetClassCPTypes(JNIEnv *env, jclass cb, unsigned char *types);
-
-/*
- * Returns the number of Constant Pool entries.
- */
-JNIEXPORT jint JNICALL
-JVM_GetClassCPEntriesCount(JNIEnv *env, jclass cb);
-
-/*
- * Returns the number of *declared* fields or methods.
- */
-JNIEXPORT jint JNICALL
-JVM_GetClassFieldsCount(JNIEnv *env, jclass cb);
-
-JNIEXPORT jint JNICALL
-JVM_GetClassMethodsCount(JNIEnv *env, jclass cb);
-
-/*
- * Returns the CP indexes of exceptions raised by a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxExceptionIndexes(JNIEnv *env, jclass cb, jint method_index,
- unsigned short *exceptions);
-/*
- * Returns the number of exceptions raised by a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxExceptionsCount(JNIEnv *env, jclass cb, jint method_index);
-
-/*
- * Returns the byte code sequence of a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxByteCode(JNIEnv *env, jclass cb, jint method_index,
- unsigned char *code);
-
-/*
- * Returns the length of the byte code sequence of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxByteCodeLength(JNIEnv *env, jclass cb, jint method_index);
-
-/*
- * A structure used to a capture exception table entry in a Java method.
- */
-typedef struct {
- jint start_pc;
- jint end_pc;
- jint handler_pc;
- jint catchType;
-} JVM_ExceptionTableEntryType;
-
-/*
- * Returns the exception table entry at entry_index of a given method.
- * Places the result in the given buffer.
- *
- * The method is identified by method_index.
- */
-JNIEXPORT void JNICALL
-JVM_GetMethodIxExceptionTableEntry(JNIEnv *env, jclass cb, jint method_index,
- jint entry_index,
- JVM_ExceptionTableEntryType *entry);
-
-/*
- * Returns the length of the exception table of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxExceptionTableLength(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the modifiers of a given field.
- * The field is identified by field_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetFieldIxModifiers(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the modifiers of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxModifiers(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the number of local variables of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxLocalsCount(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the number of arguments (including this pointer) of a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxArgsSize(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the maximum amount of stack (in words) used by a given method.
- * The method is identified by method_index.
- */
-JNIEXPORT jint JNICALL
-JVM_GetMethodIxMaxStack(JNIEnv *env, jclass cb, int index);
-
-/*
- * Is a given method a constructor.
- * The method is identified by method_index.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsConstructorIx(JNIEnv *env, jclass cb, int index);
-
-/*
- * Is the given method generated by the VM.
- * The method is identified by method_index.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsVMGeneratedMethodIx(JNIEnv *env, jclass cb, int index);
-
-/*
- * Returns the name of a given method in UTF format.
- * The result remains valid until JVM_ReleaseUTF is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetMethodIxNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of a given method in UTF format.
- * The result remains valid until JVM_ReleaseUTF is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetMethodIxSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the name of the field referred to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the name of the method referred to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of the method referred to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the signature of the field referred to at a given constant pool
- * index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldSignatureUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name referred to at a given constant pool index.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name referred to at a given constant pool index.
- *
- * The constant pool entry must refer to a CONSTANT_Fieldref.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPFieldClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the class name referred to at a given constant pool index.
- *
- * The constant pool entry must refer to CONSTANT_Methodref or
- * CONSTANT_InterfaceMethodref.
- *
- * The result is in UTF format and remains valid until JVM_ReleaseUTF
- * is called.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- */
-JNIEXPORT const char * JNICALL
-JVM_GetCPMethodClassNameUTF(JNIEnv *env, jclass cb, jint index);
-
-/*
- * Returns the modifiers of a field in calledClass. The field is
- * referred to in class cb at constant pool entry index.
- *
- * The caller must treat the string as a constant and not modify it
- * in any way.
- *
- * Returns -1 if the field does not exist in calledClass.
- */
-JNIEXPORT jint JNICALL
-JVM_GetCPFieldModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
-
-/*
- * Returns the modifiers of a method in calledClass. The method is
- * referred to in class cb at constant pool entry index.
- *
- * Returns -1 if the method does not exist in calledClass.
- */
-JNIEXPORT jint JNICALL
-JVM_GetCPMethodModifiers(JNIEnv *env, jclass cb, int index, jclass calledClass);
-
-/*
- * Releases the UTF string obtained from the VM.
- */
-JNIEXPORT void JNICALL
-JVM_ReleaseUTF(const char *utf);
-
-/*
- * Compare if two classes are in the same package.
- */
-JNIEXPORT jboolean JNICALL
-JVM_IsSameClassPackage(JNIEnv *env, jclass class1, jclass class2);
-
-/* Get classfile constants */
-#include "classfile_constants.h"
-
-/*
- * A function defined by the byte-code verifier and called by the VM.
- * This is not a function implemented in the VM.
- *
- * Returns JNI_FALSE if verification fails. A detailed error message
- * will be places in msg_buf, whose length is specified by buf_len.
- */
-typedef jboolean (*verifier_fn_t)(JNIEnv *env,
- jclass cb,
- char * msg_buf,
- jint buf_len);
-
-
-/*
- * Support for a VM-independent class format checker.
- */
-typedef struct {
- unsigned long code; /* byte code */
- unsigned long excs; /* exceptions */
- unsigned long etab; /* catch table */
- unsigned long lnum; /* line number */
- unsigned long lvar; /* local vars */
-} method_size_info;
-
-typedef struct {
- unsigned int constants; /* constant pool */
- unsigned int fields;
- unsigned int methods;
- unsigned int interfaces;
- unsigned int fields2; /* number of static 2-word fields */
- unsigned int innerclasses; /* # of records in InnerClasses attr */
-
- method_size_info clinit; /* memory used in clinit */
- method_size_info main; /* used everywhere else */
-} class_size_info;
-
-/*
- * Functions defined in libjava.so to perform string conversions.
- *
- */
-
-typedef jstring (*to_java_string_fn_t)(JNIEnv *env, char *str);
-
-typedef char *(*to_c_string_fn_t)(JNIEnv *env, jstring s, jboolean *b);
-
-/* This is the function defined in libjava.so that performs class
- * format checks. This functions fills in size information about
- * the class file and returns:
- *
- * 0: good
- * -1: out of memory
- * -2: bad format
- * -3: unsupported version
- * -4: bad class name
- */
-
-typedef jint (*check_format_fn_t)(char *class_name,
- unsigned char *data,
- unsigned int data_size,
- class_size_info *class_size,
- char *message_buffer,
- jint buffer_length,
- jboolean measure_only,
- jboolean check_relaxed);
-
-#define JVM_RECOGNIZED_CLASS_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_SUPER | \
- JVM_ACC_INTERFACE | \
- JVM_ACC_ABSTRACT | \
- JVM_ACC_ANNOTATION | \
- JVM_ACC_ENUM | \
- JVM_ACC_SYNTHETIC)
-
-#define JVM_RECOGNIZED_FIELD_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_PRIVATE | \
- JVM_ACC_PROTECTED | \
- JVM_ACC_STATIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_VOLATILE | \
- JVM_ACC_TRANSIENT | \
- JVM_ACC_ENUM | \
- JVM_ACC_SYNTHETIC)
-
-#define JVM_RECOGNIZED_METHOD_MODIFIERS (JVM_ACC_PUBLIC | \
- JVM_ACC_PRIVATE | \
- JVM_ACC_PROTECTED | \
- JVM_ACC_STATIC | \
- JVM_ACC_FINAL | \
- JVM_ACC_SYNCHRONIZED | \
- JVM_ACC_BRIDGE | \
- JVM_ACC_VARARGS | \
- JVM_ACC_NATIVE | \
- JVM_ACC_ABSTRACT | \
- JVM_ACC_STRICT | \
- JVM_ACC_SYNTHETIC)
-
-/*
- * This is the function defined in libjava.so to perform path
- * canonicalization. VM call this function before opening jar files
- * to load system classes.
- *
- */
-
-typedef int (*canonicalize_fn_t)(JNIEnv *env, char *orig, char *out, int len);
-
-/*************************************************************************
- PART 3: I/O and Network Support
- ************************************************************************/
-
-/*
- * Convert a pathname into native format. This function does syntactic
- * cleanup, such as removing redundant separator characters. It modifies
- * the given pathname string in place.
- */
-JNIEXPORT char * JNICALL
-JVM_NativePath(char *);
-
-/*
- * The standard printing functions supported by the Java VM. (Should they
- * be renamed to JVM_* in the future?
- */
-
-/* jio_snprintf() and jio_vsnprintf() behave like snprintf(3) and vsnprintf(3),
- * respectively, with the following differences:
- * - The string written to str is always zero-terminated, also in case of
- * truncation (count is too small to hold the result string), unless count
- * is 0. In case of truncation count-1 characters are written and '\0'
- * appendend.
- * - If count is too small to hold the whole string, -1 is returned across
- * all platforms. */
-
-JNIEXPORT int
-jio_vsnprintf(char *str, size_t count, const char *fmt, va_list args);
-
-JNIEXPORT int
-jio_snprintf(char *str, size_t count, const char *fmt, ...);
-
-JNIEXPORT int
-jio_fprintf(FILE *, const char *fmt, ...);
-
-JNIEXPORT int
-jio_vfprintf(FILE *, const char *fmt, va_list args);
-
-
-JNIEXPORT void * JNICALL
-JVM_RawMonitorCreate(void);
-
-JNIEXPORT void JNICALL
-JVM_RawMonitorDestroy(void *mon);
-
-JNIEXPORT jint JNICALL
-JVM_RawMonitorEnter(void *mon);
-
-JNIEXPORT void JNICALL
-JVM_RawMonitorExit(void *mon);
-
-/*
- * java.lang.management support
- */
-JNIEXPORT void* JNICALL
-JVM_GetManagement(jint version);
-
-/*
- * com.sun.tools.attach.VirtualMachine support
- *
- * Initialize the agent properties with the properties maintained in the VM.
- */
-JNIEXPORT jobject JNICALL
-JVM_InitAgentProperties(JNIEnv *env, jobject agent_props);
-
-JNIEXPORT jstring JNICALL
-JVM_GetTemporaryDirectory(JNIEnv *env);
-
-/* Generics reflection support.
- *
- * Returns information about the given class's EnclosingMethod
- * attribute, if present, or null if the class had no enclosing
- * method.
- *
- * If non-null, the returned array contains three elements. Element 0
- * is the java.lang.Class of which the enclosing method is a member,
- * and elements 1 and 2 are the java.lang.Strings for the enclosing
- * method's name and descriptor, respectively.
- */
-JNIEXPORT jobjectArray JNICALL
-JVM_GetEnclosingMethodInfo(JNIEnv* env, jclass ofClass);
-
-/* =========================================================================
- * The following defines a private JVM interface that the JDK can query
- * for the JVM version and capabilities. sun.misc.Version defines
- * the methods for getting the VM version and its capabilities.
- *
- * When a new bit is added, the following should be updated to provide
- * access to the new capability:
- * HS: JVM_GetVersionInfo and Abstract_VM_Version class
- * SDK: Version class
- *
- * Similary, a private JDK interface JDK_GetVersionInfo0 is defined for
- * JVM to query for the JDK version and capabilities.
- *
- * When a new bit is added, the following should be updated to provide
- * access to the new capability:
- * HS: JDK_Version class
- * SDK: JDK_GetVersionInfo0
- *
- * ==========================================================================
- */
-typedef struct {
- unsigned int jvm_version; /* Encoded $VNUM as specified by JEP-223 */
- unsigned int patch_version : 8; /* JEP-223 patch version */
- unsigned int reserved3 : 8;
- unsigned int reserved1 : 16;
- unsigned int reserved2;
-
- /* The following bits represents JVM supports that JDK has dependency on.
- * JDK can use these bits to determine which JVM version
- * and support it has to maintain runtime compatibility.
- *
- * When a new bit is added in a minor or update release, make sure
- * the new bit is also added in the main/baseline.
- */
- unsigned int is_attach_supported : 1;
- unsigned int : 31;
- unsigned int : 32;
- unsigned int : 32;
-} jvm_version_info;
-
-#define JVM_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
-#define JVM_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
-#define JVM_VERSION_SECURITY(version) ((version & 0x0000FF00) >> 8)
-#define JVM_VERSION_BUILD(version) ((version & 0x000000FF))
-
-JNIEXPORT void JNICALL
-JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t info_size);
-
-typedef struct {
- unsigned int jdk_version; /* Encoded $VNUM as specified by JEP-223 */
- unsigned int patch_version : 8; /* JEP-223 patch version */
- unsigned int reserved3 : 8;
- unsigned int reserved1 : 16;
- unsigned int reserved2;
-
- /* The following bits represents new JDK supports that VM has dependency on.
- * VM implementation can use these bits to determine which JDK version
- * and support it has to maintain runtime compatibility.
- *
- * When a new bit is added in a minor or update release, make sure
- * the new bit is also added in the main/baseline.
- */
- unsigned int thread_park_blocker : 1;
- unsigned int post_vm_init_hook_enabled : 1;
- unsigned int pending_list_uses_discovered_field : 1;
- unsigned int : 29;
- unsigned int : 32;
- unsigned int : 32;
-} jdk_version_info;
-
-#define JDK_VERSION_MAJOR(version) ((version & 0xFF000000) >> 24)
-#define JDK_VERSION_MINOR(version) ((version & 0x00FF0000) >> 16)
-#define JDK_VERSION_SECURITY(version) ((version & 0x0000FF00) >> 8)
-#define JDK_VERSION_BUILD(version) ((version & 0x000000FF))
-
-/*
- * This is the function JDK_GetVersionInfo0 defined in libjava.so
- * that is dynamically looked up by JVM.
- */
-typedef void (*jdk_version_info_fn_t)(jdk_version_info* info, size_t info_size);
-
-/*
- * This structure is used by the launcher to get the default thread
- * stack size from the VM using JNI_GetDefaultJavaVMInitArgs() with a
- * version of 1.1. As it is not supported otherwise, it has been removed
- * from jni.h
- */
-typedef struct JDK1_1InitArgs {
- jint version;
-
- char **properties;
- jint checkSource;
- jint nativeStackSize;
- jint javaStackSize;
- jint minHeapSize;
- jint maxHeapSize;
- jint verifyMode;
- char *classpath;
-
- jint (JNICALL *vfprintf)(FILE *fp, const char *format, va_list args);
- void (JNICALL *exit)(jint code);
- void (JNICALL *abort)(void);
-
- jint enableClassGC;
- jint enableVerboseGC;
- jint disableAsyncGC;
- jint verbose;
- jboolean debugging;
- jint debugPort;
-} JDK1_1InitArgs;
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-
-#endif /* __cplusplus */
-
-#endif /* !_JAVASOFT_JVM_H_ */
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/share/native/libjava/jdk_util.c
--- a/src/java.base/share/native/libjava/jdk_util.c Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/share/native/libjava/jdk_util.c Thu Dec 14 12:28:32 2017 +0000
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,9 @@
JNIEXPORT void
JDK_GetVersionInfo0(jdk_version_info* info, size_t info_size) {
/* These VERSION_* macros are given by the build system */
- const unsigned int version_major = VERSION_MAJOR;
- const unsigned int version_minor = VERSION_MINOR;
- const unsigned int version_security = VERSION_SECURITY;
+ const unsigned int version_major = VERSION_FEATURE;
+ const unsigned int version_minor = VERSION_INTERIM;
+ const unsigned int version_security = VERSION_UPDATE;
const unsigned int version_patch = VERSION_PATCH;
const unsigned int version_build = VERSION_BUILD;
diff -r 907bddce488c -r b6ff245c0db6 src/java.base/unix/classes/java/io/FileDescriptor.java
--- a/src/java.base/unix/classes/java/io/FileDescriptor.java Mon Dec 11 16:43:11 2017 +0000
+++ b/src/java.base/unix/classes/java/io/FileDescriptor.java Thu Dec 14 12:28:32 2017 +0000
@@ -25,10 +25,14 @@
package java.io;
+import java.lang.ref.Cleaner;
import java.util.ArrayList;
import java.util.List;
+
import jdk.internal.misc.JavaIOFileDescriptorAccess;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.ref.CleanerFactory;
+import jdk.internal.ref.PhantomCleanable;
/**
* Instances of the file descriptor class serve as an opaque handle
@@ -64,7 +68,7 @@
SharedSecrets.setJavaIOFileDescriptorAccess(
new JavaIOFileDescriptorAccess() {
public void set(FileDescriptor fdo, int fd) {
- fdo.fd = fd;
+ fdo.set(fd);
}
public int get(FileDescriptor fdo) {
@@ -79,10 +83,14 @@
return fdo.append;
}
- public void close(FileDescriptor fdo) {
+ public void close(FileDescriptor fdo) throws IOException {
fdo.close();
}
+ public void registerCleanup(FileDescriptor fdo) {
+ fdo.registerCleanup();
+ }
+
public void setHandle(FileDescriptor fdo, long handle) {
throw new UnsupportedOperationException();
}
@@ -95,6 +103,11 @@
}
/**
+ * Cleanup in case FileDescriptor is not explicitly closed.
+ */
+ private FDCleanup cleanup;
+
+ /**
* Constructs an (invalid) FileDescriptor
* object.
*/
@@ -178,6 +191,34 @@
private static native void initIDs();
/**
+ * Set the fd.
+ * If setting to -1, clear the cleaner.
+ * The {@link #registerCleanup()} method should be called for new fds.
+ * @param fd the fd or -1 to indicate closed
+ */
+ @SuppressWarnings("unchecked")
+ synchronized void set(int fd) {
+ if (fd == -1 && cleanup != null) {
+ cleanup.clear();
+ cleanup = null;
+ }
+ this.fd = fd;
+ }
+
+ /**
+ * Register a cleanup for the current raw fd.
+ * Used directly in java.io and indirectly via fdAccess.
+ * The cleanup should be registered after the fd is set in the FileDescriptor.
+ */
+ @SuppressWarnings("unchecked")
+ synchronized void registerCleanup() {
+ if (cleanup != null) {
+ cleanup.clear();
+ }
+ cleanup = FDCleanup.create(this);
+ }
+
+ /**
* Returns true, if the file was opened for appending.
*/
private static native boolean getAppend(int fd);
@@ -185,9 +226,30 @@
/**
* Close the raw file descriptor or handle, if it has not already been closed
* and set the fd and handle to -1.
+ * Clear the cleaner so the close does not happen twice.
* Package private to allow it to be used in java.io.
+ * @throws IOException if close fails
*/
- native void close();
+ @SuppressWarnings("unchecked")
+ synchronized void close() throws IOException {
+ if (cleanup != null) {
+ cleanup.clear();
+ cleanup = null;
+ }
+ close0();
+ }
+
+ /*
+ * Close the raw file descriptor or handle, if it has not already been closed
+ * and set the fd and handle to -1.
+ */
+ private native void close0() throws IOException;
+
+ /*
+ * Raw close of the file descriptor.
+ * Used only for last chance cleanup.
+ */
+ private static native void cleanupClose0(int fd) throws IOException;
/*
* Package private methods to track referents.
@@ -252,4 +314,45 @@
}
}
}
+
+ /**
+ * Cleanup for a FileDescriptor when it becomes phantom reachable.
+ * Create a cleanup if fd != -1.
+ * Subclassed from {@code PhantomCleanable} so that {@code clear} can be
+ * called to disable the cleanup when the fd is closed by any means other
+ * than calling {@link FileDescriptor#close}.
+ * Otherwise, it may close the native fd after it has been reused.
+ */
+ static final class FDCleanup extends PhantomCleanable
JList's sets the name of the renderer to List.renderer. JList
supports the following properties:
JList Specific Properties
@@ -486,7 +490,7 @@
Boolean
true
If true the renderers state is not updated, and the text
-colors come from JList's getSelectionBackground and
+colors come from JList's getSelectionBackground and
getSelectionForeground methods. If false, the renderer's state is
updated and the colors will instead come from the Style.
The Menu classes (JCheckBoxMenuItem, JMenu, JMenuItem, and
JRadioButtonMenuItem) all support the same set of properties and behave
similarly. Each component consists of two Regions: the region
@@ -536,7 +540,7 @@
prefix.arrowIcon
Icon
null
-
Icon drawn to the right of the text (or left when the
+
Icon drawn to the right of the text (or left when the
ComponentOrientation is right to left) of the text. This is
typically only defined for JMenu.
@@ -544,7 +548,7 @@
prefix.checkIcon
Icon
null
-
Icon drawn to the left of the text (or right when the
+
Icon drawn to the left of the text (or right when the
ComponentOrientation is right to left) of the text. This is
typically only defined for JCheckBoxMenuItem and JRadioButtonMenuItem
to provide the check or radio button.
@@ -561,7 +565,7 @@
prefix.textIconGap
Integer
4
-
Padding between the icon and text. Refer to the javadoc for
+
Padding between the icon and text. Refer to the javadoc for
javax.swing.AbstractButton#setIconTextGap(int) for details of how
this is used.
JOptionPane is a composite component and may consist of numerous child
components, they are: OptionPane.button, OptionPane.label,
OptionPane.comboBox, OptionPane.scrollPane, OptionPane.list,
@@ -623,7 +627,7 @@
OptionPane.buttonOrientation
Integer
SwingConstants.CENTER
-
How the buttons should be layed out, one of
+
How the buttons should be layed out, one of
SwingConstants.LEFT, SwingConstants.RIGHT or SwingConstants.CENTER
(this will be flipped when in a right to left locale).
All of the separator classes, JSeparator, JPopupMenu.Separator and
JToolBar.Separator use the same property:
@@ -856,7 +860,7 @@
Separator.thickness
Integer
2
-
Preferred width, for vertically aligned separators, or
+
Preferred width, for vertically aligned separators, or
preferred height for horizontally aligned separators. The resulting
preferred size will include the Insets.
@@ -875,20 +879,21 @@
ToolBar.separatorSize
Dimension
null
-
The value of this is passed to the javax.swing.JToolBar$Separator#setSeparatorSize(java.awt.Dimension)
-method. If unspecified setSeparatorSize is not
-invoked.
-
+
The value of this is passed to the
+ javax.swing.JToolBar$Separator#setSeparatorSize(java.awt.Dimension)
+ method. If unspecified setSeparatorSize is not invoked.
+
JScrollPane is unique in that it provides a method for setting
the Border around the JViewport with JViewport throwing an
IllegalArgumentException from setBorder. To
accommodate this a special border is installed on the
- JScrollPane that uses the
+ JScrollPane that uses the
insets from the key
ScrollPane.viewportBorderInsets. The
SynthPainter method
@@ -913,7 +918,7 @@
-
JSplitPane is a composite component that will contain a divider and
potentially two buttons, if setOneTouchExpandable(true) has been
invoked. The two buttons will be named:
@@ -950,7 +955,7 @@
SplitPane.oneTouchExpandable
Boolean
null
-
If non null, the value of this is passed to
+
If non null, the value of this is passed to
setOneTouchExpandable.
JTable sets the name of the renderer to Table.cellRenderer.
JTable supports the following properties:
JTable Specific Properties
@@ -1108,7 +1113,7 @@
Boolean
true
If true the renderers state is not updated, and the text
-colors come from JTable's getSelectionBackground and
+colors come from JTable's getSelectionBackground and
getSelectionForeground methods. If false, the renderer's state is
updated and the colors will instead come from the Style.
@@ -1116,7 +1121,7 @@
Table.rendererUseUIBorder
Boolean
true
-
If true setBorder on the renderer will succeed
+
If true setBorder on the renderer will succeed
regardless of the border passed in, otherwise setBorder on the
renderer will only succeed if it is a Synth Border.
Each of the Button classes (JButton, JCheckBox, JRadioButton,
JToggleButton and SynthArrowButton) support a similar set of properties.
These properties are:
@@ -1250,23 +1255,29 @@
prefix.contentAreaFilled
Integer
true
-
Refer to the javadoc of javax.swing.AbstractButton#contentAreaFilled(boolean) for details
-of how this is used. It is up to the Painter to properly honor this
-property.
-
+
Refer to the javadoc of
+ javax.swing.AbstractButton#contentAreaFilled(boolean)
+ for details of how this is used. It is up to the Painter to properly honor
+ this property.
+
+
prefix.iconTextGap
Integer
-
If unspecified, JButton.setIconTextGap is not invoked.
-
Padding between the icon and text. Refer to the javadoc of javax.swing.AbstractButton#setIconTextGap(int) for details of how
-this is used.
+
If unspecified, JButton.setIconTextGap is not invoked.
+
Padding between the icon and text. Refer to the javadoc of
+ javax.swing.AbstractButton#setIconTextGap(int)
+ for details of how this is used.
+
prefix.margin
Insets
Empty Insets (0, 0, 0, 0)
-
Margin for the JButton. Refer to the javadoc of javax.swing.AbstractButton#setMargin(java.awt.Insets) for details
-of how the margin is used.
+
Margin for the JButton. Refer to the javadoc of
+ javax.swing.AbstractButton#setMargin(java.awt.Insets) for
+ details of how the margin is used.
+
prefix.textShiftOffset
@@ -1281,7 +1292,7 @@
Prefix is one of: Button, CheckBox, RadioButton or
JToggleButton.