Mercurial > hg > shenandoah-preopenjdk-archive > openjdk8 > jdk
changeset 2585:13029a61b16b jdk7-b102
Merge
author | lana |
---|---|
date | Tue, 20 Jul 2010 22:21:31 -0700 |
parents | 6c4450bbad6d (current diff) c5a436f053aa (diff) |
children | 6488b70a23cc |
files | test/java/nio/channels/ServerSocketChannel/AcceptAddress.java test/java/nio/charset/coders/Surrogate.java test/tools/launcher/Makefile.SolarisRunpath test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so test/tools/launcher/lib/i386/lib32/liblibrary.so test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so test/tools/launcher/lib/sparc/lib32/liblibrary.so test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so test/tools/launcher/lib/sparc/lib64/liblibrary.so |
diffstat | 236 files changed, 10638 insertions(+), 6217 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/common/shared/Defs-javadoc.gmk Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,93 @@ +# +# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +# Copyright year for beginning of Java and some of the apis +# (Needed when creating the javadocs) +FIRST_COPYRIGHT_YEAR = 1993 +DOMAPI_FIRST_COPYRIGHT_YEAR = 2005 +MIRROR_FIRST_COPYRIGHT_YEAR = 2004 +DOCLETAPI_FIRST_COPYRIGHT_YEAR = 1993 +TAGLETAPI_FIRST_COPYRIGHT_YEAR = 1993 +JDI_FIRST_COPYRIGHT_YEAR = 1999 +JAAS_FIRST_COPYRIGHT_YEAR = 1998 +JGSS_FIRST_COPYRIGHT_YEAR = 2000 +SMARTCARDIO_FIRST_COPYRIGHT_YEAR = 2005 +HTTPSERVER_FIRST_COPYRIGHT_YEAR = 2005 +MGMT_FIRST_COPYRIGHT_YEAR = 2003 +ATTACH_FIRST_COPYRIGHT_YEAR = 2005 +JCONSOLE_FIRST_COPYRIGHT_YEAR = 2006 +SCTPAPI_FIRST_COPYRIGHT_YEAR = 2009 +TRACING_FIRST_COPYRIGHT_YEAR = 2008 +TREEAPI_FIRST_COPYRIGHT_YEAR = 2005 +JNLP_FIRST_COPYRIGHT_YEAR = 1998 +PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007 + +# Oracle name +COMPANY_NAME = Oracle and/or its affiliates + +# Copyright address +COMPANY_ADDRESS = 500 Oracle Parkway<br>Redwood Shores, CA 94065 USA. + +# The trademark symbol +TRADEMARK = ™ + +# Common copyright lines used +# The word "Copyright" might optionally be a link to the file cpyr.html. +# The first year of copyright may vary or not be available. +# The address to the company might be optional. +COMMA:= , +EMPTY:= +SPACE:=$(EMPTY) $(EMPTY) +COPYRIGHT_SYMBOL = &\#x00a9; +# Macros to handle the optional empty args. +# (The GNU make 3.78.1 "if" conditional is broken, fixed in GNU make 3.81) +define OptionalCopyrightUrl # url +$(shell \ + if [ "$1" != "" ] ; then \ + printf "<a href=\"%s\">Copyright</a>" "$1"; \ + else \ + printf "Copyright"; \ + fi) +endef +define OptionalCopyrightFirstYear # year +$(shell \ + if [ "$1" != "" ] ; then \ + printf "%s," "$1";\ + fi) +endef +define OptionalCompanyAddress # address +$(shell \ + if [ "$1" != "" ] ; then \ + printf "%s" "$1";\ + fi) +endef +define CopyrightLine # optionalurl optionalfirstyear optionaladdress +$(call OptionalCopyrightUrl,$1) $(COPYRIGHT_SYMBOL)\ +$(call OptionalCopyrightFirstYear,$2) $(COPYRIGHT_YEAR),\ +$(COMPANY_NAME).\ +$(call OptionalCompanyAddress,$3)\ +All rights reserved. +endef +
--- a/make/common/shared/Defs-windows.gmk Thu Jul 15 20:11:45 2010 -0700 +++ b/make/common/shared/Defs-windows.gmk Tue Jul 20 22:21:31 2010 -0700 @@ -230,7 +230,8 @@ # Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit] ifeq ($(ARCH_DATA_MODEL), 32) - # Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat) + # Try looking in MSVCDIR or MSVCDir area first + # (set by vcvars32.bat for VC .NET, not defined in the VC 2008/2010) ifdef MSVCDIR xMSVCDIR :="$(subst \,/,$(MSVCDIR))" _msvc_dir :=$(call FullPath,$(xMSVCDIR)) @@ -238,11 +239,6 @@ ifdef MSVCDir xMSVCDIR :="$(subst \,/,$(MSVCDir))" _msvc_dir :=$(call FullPath,$(xMSVCDIR)) - else - ifneq ($(_program_files),) - xMSVCDIR :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7" - _msvc_dir :=$(call FullPath,$(xMSVCDIR)) - endif endif endif # If we still don't have it, look for VSnnCOMNTOOLS (newest first),
--- a/make/docs/Makefile Thu Jul 15 20:11:45 2010 -0700 +++ b/make/docs/Makefile Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,4 @@ -# -# Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,6 +29,41 @@ PRODUCT=docs include $(BUILDDIR)/common/Defs.gmk +# Get CopyrightLine macro and other shared variables +include $(BUILDDIR)/common/shared/Defs-javadoc.gmk + +# Url to root of documents +DOCSDIR_URL = {@docroot}/$(GET2DOCSDIR) + +# Url to copyright html file +COPYRIGHT_URL-7 = $(DOCSDIR_URL)/legal/cpyr.html +COPYRIGHT_URL = $(COPYRIGHT_URL-$(JDK_MINOR_VERSION)) + +# Url to bug filing site +BUG_SUBMIT_URL = http://bugs.sun.com/services/bugreport/index.jsp + +# Common line for how to submit a bug or rfe +BUG_SUBMIT_LINE = <a href=\"$(BUG_SUBMIT_URL)\">Submit a bug or feature</a> + +# Url to devdocs page +# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html +DEV_DOCS_URL-5 = http://java.sun.com/j2se/1.5.0/docs +DEV_DOCS_URL-6 = http://download.oracle.com/docs/cd/E17409_01/javase/6/docs +DEV_DOCS_URL-7 = http://download.oracle.com/docs/cd/E17409_01/javase/7/docs +DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION)) + +# Url to Java Language Spec +JLS3_URL = http://java.sun.com/docs/books/jls/ + +# Common Java trademark line +JAVA_TRADEMARK_LINE = Java is a trademark or registered trademark of \ +$(COMPANY_NAME) in the US and other countries. + +# +# Definitions for imported components +# +include $(BUILDDIR)/common/internal/ImportComponents.gmk + # We override whatever the max VM memory setting is here. # NOTE: javadoc will not complete without these larger settings. # WARNING: This could cause thrashing on low memory machines. @@ -39,418 +73,155 @@ MAX_VM_MEMORY = 512 endif -# -# Variables used by docs target +# List of all possible directories for javadoc to look for sources +# NOTE: Quotes are required around sourcepath argument only on Windows. +# Otherwise, you get "No packages or classes specified." due +# to $(CLASSPATH_SEPARATOR) being interpreted as an end of +# command (newline or shell ; character) +ALL_SOURCE_DIRS = $(SHARE_SRC)/classes \ + $(IMPORTSRCDIR) \ + $(GENSRCDIR) \ + $(SHARE_SRC)/../solaris/classes \ + $(SHARE_SRC)/../windows/classes \ + $(SHARE_SRC)/doc/stub +EMPTY:= +SPACE:= $(EMPTY) $(EMPTY) +RELEASEDOCS_SOURCEPATH = \ + $(subst $(SPACE),$(CLASSPATH_SEPARATOR),$(strip $(ALL_SOURCE_DIRS))) + +# Prep for javadoc creation, assumes $@ is an index.html file +define prep-javadoc +@if [ -f "$@" -a "$?" != "" ] ; then \ + $(ECHO) "# Dependencies have changed: $?"; \ +fi +$(RM) -r $(@D) +$(MKDIR) -p $(@D) +endef + +# A cache of the directories in ALL_SOURCE_DIRS +DIRECTORY_CACHE = $(DOCSTMPDIR)/directory.cache + +# Given a list of packages, return a list of files or dirs to be dependent on +# (Currently only returning a list of directories) +define PackageDependencies # packages +$(shell \ + if [ "$1" != "" -a -f $(DIRECTORY_CACHE) ] ; then \ + for p in $1 ; do \ + pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; \ + $(CAT) $(DIRECTORY_CACHE) | $(GREP) "/$${pd}/" ; \ + done; \ + fi \ +) +endef + +# Given a list of packages, add packages that exist to $@, print summary +define PackageFilter # packages +@if [ "$1" != "" ] ; then \ + for p in $1 ; do \ + pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; \ + found="false"; \ + for cp in $(ALL_SOURCE_DIRS) ; do \ + if [ -d $${cp}/$${pd} ] ; then \ + $(ECHO) "$${p}" >> $@; \ + found="true"; \ + break; \ + fi; \ + done; \ + if [ "$${found}" = "false" ] ; then \ + $(ECHO) "WARNING: Package not found: $${p}"; \ + fi; \ + done; \ +fi +endef + +# Print out a summary of the javadoc command about to be run +define JavadocSummary # optionsfile packagesfile +@$(ECHO) "# Summary for $@";\ + $(ECHO) "# Options (`$(BASENAME) $1`):"; $(SED) -e 's@^@# @' $1; \ + $(ECHO) "# Packages (`$(BASENAME) $2`):";$(SED) -e 's@^@# @' $2 +endef + # -DOCSTMPDIR = $(TEMPDIR)/doctmp +# Temporary directory for javadoc creation +# +DOCSTMPDIR = $(TEMPDIR)/doctmp + +# +# Different api directories created from root directory +# +COREAPI_DOCSDIR = $(DOCSDIR)/api +JDK_API_DOCSDIR = $(DOCSDIR)/jdk/api +JRE_API_DOCSDIR = $(DOCSDIR)/jre/api +PLATFORM_DOCSDIR = $(DOCSDIR)/platform + +# The non-core api javadocs need to be able to access the root of the core +# api directory, so for jdk/api or jre/api to get to the core api/ +# directory we would use this: +JDKJRE2COREAPI = ../../api + +# Common bottom argument +define CommonBottom # year +<font size=\"-1\"><p> $(call CopyrightLine,,$1,)</font> +endef +# Common trademark bottom argument (Not sure why this is used sometimes) +define CommonTrademarkBottom # year +<font size=\"-1\">\ +$(BUG_SUBMIT_LINE)<br>$(JAVA_TRADEMARK_LINE)<br>\ +$(call CopyrightLine,,$1,$(COMPANY_ADDRESS))\ +</font> +endef + +# Core api bottom argument (with special sauce) +COREAPI_BOTTOM = <font size=\"-1\"> $(BUG_SUBMIT_LINE)\ +<br>For further API reference and developer documentation, \ +see <a href=\"$(DEV_DOCS_URL)\" target=\"_blank\">Java SE Documentation</a>. \ +That documentation contains more detailed, developer-targeted descriptions, \ +with conceptual overviews, definitions of terms, workarounds, \ +and working code examples.<p>\ +$(call CopyrightLine,$(COPYRIGHT_URL),$(FIRST_COPYRIGHT_YEAR),)\ +</font> + +# Common javadoc options used by all COMMON_JAVADOCFLAGS = \ - $(NO_PROPRIETARY_API_WARNINGS) \ + $(NO_PROPRIETARY_API_WARNINGS) \ -source 1.5 \ -quiet \ -use \ -keywords \ - $(JAVADOC_VM_MEMORY_FLAGS) \ $(ADDITIONAL_JAVADOCFLAGS) ADDITIONAL_JAVADOCFLAGS = -CORE_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - $(TAGS) \ - -encoding ISO-8859-1 \ - -splitIndex \ - -doctitle $(DOCTITLE_SWITCH) \ - -windowtitle $(WINDOWTITLE_SWITCH) \ - -header $(HEADER_SWITCH) \ - $(TOPOPTION) \ - -bottom $(JAVADOCBOTTOM_SWITCH) \ - $(OVERVIEW_OPTION) - -DRAFT = '<br><strong>DRAFT '$(MILESTONE)-$(BUILD_NUMBER)'</strong>' -THIS_YEAR := $(shell $(DATE) | $(SED) -e 's/ / /g' | $(CUT) -d' ' -f6) -TRADEMARK = &\#x2122; - -IGNORED_TAGS = beaninfo revised since.unbundled spec specdefault Note ToDo - -JLS3_URL = http://java.sun.com/docs/books/jls/ -JLS3_CITE = <a href="$(JLS3_URL)"> \ - The Java Language Specification, Third Edition</a> -TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:' - -TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3) - -ifeq ($(MILESTONE), fcs) - DOCTITLE_SWITCH = $(JAVADOCTITLE) - WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE) - HEADER_SWITCH = $(JAVADOCHEADER) - TOPOPTION= - JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM) - OVERVIEW_OPTION = -overview $(JAVADOCOVERVIEW) -else - DOCTITLE_SWITCH = $(JAVADOCTITLE_EARLYACCESS)$(DRAFT) - WINDOWTITLE_SWITCH = $(JAVADOCWINDOWTITLE)" $(BUILD_NUMBER)" - HEADER_SWITCH = $(JAVADOCHEADER)$(DRAFT) - JAVADOCBOTTOM_SWITCH= $(JAVADOCBOTTOM_EARLYACCESS) - TOPOPTION= -top $(JAVADOCTOP_EARLYACCESS) - OVERVIEW_OPTION = +# Draft used for non-fcs documents +JDK_IS_FCS = false +DRAFT_HEADER = +ifeq ($(JDK_MINOR_VERSION),5) + JDK_IS_FCS = true +endif +ifeq ($(JDK_MINOR_VERSION),6) + JDK_IS_FCS = true +endif +ifeq ($(JDK_IS_FCS),false) + ifneq ($(MILESTONE), fcs) + DRAFT_HEADER = <br><strong>DRAFT $(MILESTONE)-$(BUILD_NUMBER)</strong> + DRAFT_BOTTOM = <br><strong>DRAFT $(MILESTONE)-$(BUILD_NUMBER)</strong> + DRAFT_WINTITLE = $(BUILD_NUMBER) + # Early access top text (not used in FCS releases) + COREAPI_TOP_EARLYACCESS = \ +<div style=\"background-color: \#EEEEEE\"> \ +<div style=\"padding: 6px; margin-top: 2px; margin-bottom: 6px; \ +margin-left: 6px; margin-right: 6px; text-align: justify; \ +font-size: 80%; font-family: Helvetica, Arial, sans-serif; \ +font-weight: normal;\"> \ +Please note that the specifications and other information \ +contained herein are not final and are subject to change. \ +The information is being made available to you solely for purpose of \ +evaluation. \ +</div> </div> + endif endif -JAVADOCTITLE = 'Java$(TRADEMARK) Platform, Standard Edition $(JDK_MINOR_VERSION)<br>API Specification' -JAVADOCWINDOWTITLE = 'Java Platform SE $(JDK_MINOR_VERSION)' -JAVADOCHEADER = '<strong>Java$(TRADEMARK) Platform<br>Standard Ed. $(JDK_MINOR_VERSION)</strong>' -JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>For further API reference and developer documentation, see <a href="{@docroot}/../../webnotes/devdocs-vs-specs.html">Java SE Developer Documentation</a>. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples. <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>. Also see the <a href="http://java.sun.com/docs/redist.html">documentation redistribution policy</a>.</font>' -JAVADOCOVERVIEW = $(SHARE_SRC)/classes/overview-core.html - -# -# Early access top and bottom text (for snapshots, beta and rc) -# -JAVADOCTOP_EARLYACCESS = '<div style="background-color: \#EEEEEE"> <div style="padding: 6px; margin-top: 2px; margin-bottom: 6px; margin-left: 6px; margin-right: 6px; text-align: justify; font-size: 80%; font-family: Helvetica, Arial, sans-serif; font-weight: normal;"> Please note that this documentation is not final and is subject to change. </div> </div>' -JAVADOCBOTTOM_EARLYACCESS = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a> <p>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to <a href="{@docroot}/../legal/license.html">license terms</a>.</font>' -JAVADOCTITLE_EARLYACCESS = $(subst Specification,Documentation,$(JAVADOCTITLE)) - -# -# Variables used by domapidocs target -# - -DOMAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -splitIndex \ - -doctitle $(DOMAPI_JAVADOCTITLE) \ - -windowtitle $(DOMAPI_JAVADOCWINDOWTITLE) \ - -header $(DOMAPI_JAVADOCHEADER) \ - -bottom $(DOMAPI_JAVADOCBOTTOM) \ - -group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP) -DOMAPI_JAVADOCTITLE = 'Common DOM API' -DOMAPI_JAVADOCWINDOWTITLE = 'Common DOM API' -DOMAPI_JAVADOCHEADER = '<strong>Common DOM API</strong>' -DOMAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>' -DOMAPI_GROUPNAME = "Packages" -DOMAPI_REGEXP = "com.sun.java.browser.dom:org.w3c.dom*" -# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by mirrordocs target -# - -MIRROR_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -doctitle $(MIRROR_JAVADOCTITLE) \ - -windowtitle $(MIRROR_JAVADOCWINDOWTITLE) \ - -header $(MIRROR_JAVADOCHEADER) \ - -bottom $(MIRROR_JAVADOCBOTTOM) \ - -group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP) \ - -overview $(MIRROR_OVERVIEW) -MIRROR_JAVADOCTITLE = 'Mirror API' -MIRROR_JAVADOCWINDOWTITLE = 'Mirror API' -MIRROR_JAVADOCHEADER = '<strong>Mirror API</strong>' -MIRROR_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>' -MIRROR_GROUPNAME = "Packages" -MIRROR_OVERVIEW = $(IMPORTSRCDIR)/com/sun/mirror/overview.html -MIRROR_REGEXP = "com.sun.mirror.*" -MIRROR_DESTDIR = $(DOCSDIR)/jdk/api/apt/mirror -MIRROR_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/ -# MIRROR_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by docletapidocs target -# - -DOCLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -breakiterator \ - -encoding ascii \ - -doctitle $(DOCLETAPI_JAVADOCTITLE) \ - -windowtitle $(DOCLETAPI_JAVADOCWINDOWTITLE) \ - -header $(DOCLETAPI_JAVADOCHEADER) \ - -bottom $(DOCLETAPI_JAVADOCBOTTOM) \ - -group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP) -DOCLETAPI_JAVADOCTITLE = 'Doclet API' -DOCLETAPI_JAVADOCWINDOWTITLE = 'Doclet API' -DOCLETAPI_JAVADOCHEADER = '<strong>Doclet API</strong>' -DOCLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>' -DOCLETAPI_GROUPNAME = "Packages" -DOCLETAPI_REGEXP = "com.sun.javadoc" -DOCLETAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/ -# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by tagletapidocs target -# - -TAGLETAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nonavbar \ - -noindex \ - -bottom $(TAGLETAPI_JAVADOCBOTTOM) -TAGLETAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Submit a bug or feature</a><br>Java is a trademark or registered trademark of Sun Microsystems, Inc. in the US and other countries.<br>Copyright 1993-$(THIS_YEAR) Sun Microsystems, Inc. 4150 Network Circle<br>Santa Clara, California, 95054, U.S.A. All Rights Reserved.</font>' -# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk - -# -# Variables used by jdi target -# - -JPDA_SOURCEPATH = $(TOPDIR)/src/share/classes - -JDI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(DOCSDIR)/jdk/api/jpda/jdi \ - -sourcepath $(JPDA_SOURCEPATH) \ - -windowtitle $(JDI_WINDOWTITLE) \ - -doctitle $(JDI_DOCTITLE) \ - -header $(JDI_HEADER) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ \ - -overview $(JPDA_SOURCEPATH)/jdi-overview.html -JDI_WINDOWTITLE = "Java Debug Interface" -JDI_DOCTITLE = "Java$(TRADEMARK) Debug Interface" -JDI_HEADER = "Java Debug Interface" -# JDI_PKGS is located in NON_CORE_PKGS.gmk - -# Variables used by security components -SECURITYAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>' - -# -# Variables used by JAAS target -# -# NOTE: Quotes are required around sourcepath argument only on Windows. Otherwise, -# you get "No packages or classes specified." due to $(CLASSPATH_SEPARATOR) -# being interpreted as an end of command (newline) - -JAAS_SOURCEPATH = "$(TOPDIR)/src/share/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/solaris/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/windows/classes$(CLASSPATH_SEPARATOR)$(TOPDIR)/src/linux/classes" -JAAS_DOCDIR = $(DOCSDIR)/jre/api/security/jaas/spec -JAAS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(JAAS_DOCDIR) \ - -sourcepath $(JAAS_SOURCEPATH) \ - -windowtitle $(JAAS_WINDOWTITLE) \ - -doctitle $(JAAS_DOCTITLE) \ - -header $(JAAS_JAVADOCHEADER) \ - -bottom $(SECURITYAPI_JAVADOCBOTTOM) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ \ - -overview $(TOPDIR)/src/share/classes/com/sun/security/auth/jaas-overview.html -JAAS_WINDOWTITLE = "Java Authentication and Authorization Service " -JAAS_DOCTITLE = "Java$(TRADEMARK) Authentication and Authorization Service" -JAAS_JAVADOCHEADER = "JAAS" -# JAAS_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by JGSS target -# - -JGSS_SOURCEPATH = $(TOPDIR)/src/share/classes -JGSS_DOCDIR = $(DOCSDIR)/jre/api/security/jgss/spec - -JGSS_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(JGSS_DOCDIR) \ - -sourcepath $(JGSS_SOURCEPATH) \ - -windowtitle $(JGSS_WINDOWTITLE) \ - -doctitle $(JGSS_DOCTITLE) \ - -header $(JGSS_JAVADOCHEADER) \ - -bottom $(SECURITYAPI_JAVADOCBOTTOM) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ \ - -overview $(JGSS_SOURCEPATH)/com/sun/security/jgss/jgss-overview.html - -JGSS_WINDOWTITLE = "Java GSS-API Utilities " -JGSS_DOCTITLE = "Java$(TRADEMARK) GSS-API Utilities" -JGSS_JAVADOCHEADER = "Java GSS-API Utilities" -# JGSS_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by SMARTCARDIO target -# - -SMARTCARDIO_SOURCEPATH = $(TOPDIR)/src/share/classes -SMARTCARDIO_DOCDIR = $(DOCSDIR)/jre/api/security/smartcardio/spec - -SMARTCARDIO_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(SMARTCARDIO_DOCDIR) \ - -sourcepath $(SMARTCARDIO_SOURCEPATH) \ - -windowtitle $(SMARTCARDIO_WINDOWTITLE) \ - -doctitle $(SMARTCARDIO_DOCTITLE) \ - -header $(SMARTCARDIO_JAVADOCHEADER) \ - -bottom $(SECURITYAPI_JAVADOCBOTTOM) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ - -SMARTCARDIO_WINDOWTITLE = "Java Smart Card I/O" -SMARTCARDIO_DOCTITLE = "Java$(TRADEMARK) Smart Card I/O" -SMARTCARDIO_JAVADOCHEADER = "Java Smart Card I/O" -# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by TRACING target -# - -TRACING_SOURCEPATH = $(TOPDIR)/src/share/classes -TRACING_DOCDIR = $(DOCSDIR)/jre/api/tracing - -TRACING_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(TRACING_DOCDIR) \ - -sourcepath $(TRACING_SOURCEPATH) \ - -windowtitle $(TRACING_WINDOWTITLE) \ - -doctitle $(TRACING_DOCTITLE) \ - -header $(TRACING_JAVADOCHEADER) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ - -TRACING_WINDOWTITLE = "Tracing" -TRACING_DOCTITLE = "Java$(TRADEMARK) Platform Tracing" -TRACING_JAVADOCHEADER = "Platform Tracing" -# TRACING_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by HTTPSERVER target -# - -HTTPSERVER_SOURCEPATH = $(TOPDIR)/src/share/classes -HTTPSERVER_DOCDIR = $(DOCSDIR)/jre/api/net/httpserver/spec - -HTTPSERVER_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(HTTPSERVER_DOCDIR) \ - -sourcepath $(HTTPSERVER_SOURCEPATH) \ - -windowtitle $(HTTPSERVER_WINDOWTITLE) \ - -doctitle $(HTTPSERVER_DOCTITLE) \ - -header $(HTTPSERVER_JAVADOCHEADER) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ - -HTTPSERVER_WINDOWTITLE = "Java HTTP Server" -HTTPSERVER_DOCTITLE = "Java$(TRADEMARK) HTTP Server" -HTTPSERVER_JAVADOCHEADER = "Java HTTP Server" -# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by sctp target -# - -SCTPAPI_SOURCEPATH = $(TOPDIR)/src/share/classes -SCTPAPI_DOCDIR = $(DOCSDIR)/jre/api/nio/sctp/spec - -SCTPAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(SCTPAPI_DOCDIR) \ - -sourcepath $(SCTPAPI_SOURCEPATH) \ - -windowtitle $(SCTPAPI_WINDOWTITLE) \ - -doctitle $(SCTPAPI_DOCTITLE) \ - -header $(SCTPAPI_JAVADOCHEADER) \ - -bottom $(SCTPAPI_JAVADOCBOTTOM) \ - -linkoffline ../../../../../api $(DOCSDIR)/api/ - -SCTPAPI_WINDOWTITLE = "SCTP API" -SCTPAPI_DOCTITLE = "SCTP API" -SCTPAPI_JAVADOCHEADER = "SCTP API" -SCTPAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>' -# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by jvmti target -# -JVMTI_DOCS_SUBDIR = platform/jvmti -JVMTI_HTML = $(HOTSPOT_DOCS_IMPORT_PATH)/$(JVMTI_DOCS_SUBDIR)/jvmti.html - -# -# Variables used by mgmt target -# -MGMT_DOCDIR = $(DOCSDIR)/jre/api/management/ -MGMT_EXT_DIR = $(MGMT_DOCDIR)/extension -MGMT_SOURCEPATH = $(TOPDIR)/src/share/classes -JVM_MIB_NAME = JVM-MANAGEMENT-MIB.mib -JVM_MIB_SRC = $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME) - -ifdef OPENJDK - COPY-MIB-TARGET = -else - COPY-MIB-TARGET = copy-mib -endif -MGMT_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(MGMT_EXT_DIR) \ - -sourcepath $(MGMT_SOURCEPATH) \ - -windowtitle $(MGMT_WINDOWTITLE) \ - -doctitle $(MGMT_DOCTITLE) \ - -header $(MGMT_HEADER) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ \ - -overview $(MGMT_SOURCEPATH)/com/sun/management/mgmt-overview.html -MGMT_WINDOWTITLE = "Monitoring and Management Interface for the Java Platform" -MGMT_DOCTITLE = "Monitoring and Management Interface for the Java$(TRADEMARK) Platform" -MGMT_HEADER = "Monitoring and Management Interface for the Java Platform" -# MGMT_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by attach target -# - -ATTACH_SOURCEPATH = $(TOPDIR)/src/share/classes -ATTACH_DOCDIR = $(DOCSDIR)/jdk/api/attach/spec -ATTACH_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(ATTACH_DOCDIR) \ - -sourcepath $(ATTACH_SOURCEPATH) \ - -windowtitle $(ATTACH_WINDOWTITLE) \ - -doctitle $(ATTACH_DOCTITLE) \ - -header $(ATTACH_HEADER) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ -ATTACH_WINDOWTITLE = "Attach API" -ATTACH_DOCTITLE = "Attach API" -ATTACH_HEADER = "Attach API" -# ATTACH_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by jconsole target -# - -JCONSOLE_SOURCEPATH = $(TOPDIR)/src/share/classes -JCONSOLE_DOCDIR = $(DOCSDIR)/jdk/api/jconsole/spec -JCONSOLE_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -nodeprecatedlist \ - -d $(JCONSOLE_DOCDIR) \ - -sourcepath $(JCONSOLE_SOURCEPATH) \ - -windowtitle $(JCONSOLE_WINDOWTITLE) \ - -doctitle $(JCONSOLE_DOCTITLE) \ - -header $(JCONSOLE_HEADER) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ -JCONSOLE_WINDOWTITLE = "JConsole API" -JCONSOLE_DOCTITLE = "JConsole API" -JCONSOLE_HEADER = "JConsole API" -# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk - -# -# Variables used by treeapidocs target -# - -TREEAPI_JAVADOCFLAGS = $(COMMON_JAVADOCFLAGS) \ - -encoding ascii \ - -doctitle $(TREEAPI_JAVADOCTITLE) \ - -windowtitle $(TREEAPI_JAVADOCWINDOWTITLE) \ - -header $(TREEAPI_JAVADOCHEADER) \ - -bottom $(TREEAPI_JAVADOCBOTTOM) \ - -group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP) -# -# -overview $(TREEAPI_OVERVIEW) -# -TREEAPI_JAVADOCTITLE = 'Compiler Tree API' -TREEAPI_JAVADOCWINDOWTITLE = 'Compiler Tree API' -TREEAPI_JAVADOCHEADER = '<strong>Compiler Tree API</strong>' -TREEAPI_JAVADOCBOTTOM = '<font size="-1"><a href="http://bugs.sun.com/services/bugreport/index.jsp">Report a bug or request a feature.</a><br>Copyright $(THIS_YEAR) Sun Microsystems, Inc. All Rights Reserved. Use is subject to license terms.</font>' -TREEAPI_GROUPNAME = "Packages" -TREEAPI_OVERVIEW = $(SHARE_SRC)/classes/com/sun/source/overview.html -TREEAPI_REGEXP = "com.sun.source.*" -TREEAPI_DESTDIR = $(DOCSDIR)/jdk/api/javac/tree -TREEAPI_LINKOPT = -linkoffline ../../../../api $(DOCSDIR)/api/ -# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk - -# -# Path where javadoc should find source files for release docs -# -RELEASEDOCS_SRCPATH = "$(SHARE_SRC)/classes$(CLASSPATH_SEPARATOR)$(PLATFORM_SRC)/classes$(CLASSPATH_SEPARATOR)$(GENSRCDIR)$(CLASSPATH_SEPARATOR)$(SHARE_SRC)/doc/stub$(CLASSPATH_SEPARATOR)$(CLOSED_SRC)/share/classes$(CLASSPATH_SEPARATOR)$(IMPORTSRCDIR)" +################################################################# # # CORE_PKGS environment variable has been moved to the following file @@ -463,30 +234,13 @@ # include NON_CORE_PKGS.gmk -# Targets for all APIs other than the core platform APIs -ALL_OTHER_TARGETS = \ - mirrordocs \ - docletapidocs \ - tagletapidocs \ - domapidocs \ - jpdadocs \ - jaasdocs \ - jgssdocs \ - smartcardiodocs \ - tracingdocs \ - httpserverdocs \ - sctpdocs \ - mgmtdocs \ - attachdocs \ - jconsoledocs \ - treeapidocs +################################################################# -.PHONY: all docs -all docs: coredocs otherdocs +# +# Default target is same as docs target, create core api and all others it can +# -.PHONY: otherdocs -otherdocs: ${ALL_OTHER_TARGETS} - +all docs: coredocs otherdocs ################################################################# # Production Targets -- USE THESE TARGETS WHEN: @@ -496,9 +250,9 @@ # the downloaded doc bundle. # # See: Notes.html#releaseTargets -# Note: Spaces preceed ifdef/ifndef indents. Tabs preceed target commands (!) +# Note: Spaces precede ifdef/ifndef indents. Tabs precede target commands (!) # -.PHONY: sanitycheckcoredocs + sanitycheckcoredocs: @$(ECHO) "" @$(ECHO) "Building core api docs with these values:" @@ -512,199 +266,942 @@ exit 1 endif -# Maximize performance and ensure that build number & milestone are set. -.PHONY: rel-coredocs -rel-coredocs: sanitycheckcoredocs - @# ######## release version of core packages ######## - $(MAKE) coredocs +############################################################# +# +# coredocs +# +COREAPI_DOCTITLE = Java$(TRADEMARK) Platform, Standard Edition \ +$(JDK_MINOR_VERSION)<br>API Specification +COREAPI_WINDOWTITLE = Java Platform SE $(JDK_MINOR_VERSION) +COREAPI_HEADER = \ +<strong>Java$(TRADEMARK) Platform<br>Standard Ed. $(JDK_MINOR_VERSION)</strong> + +# Ignored tags +IGNORED_TAGS = beaninfo revised since.unbundled spec specdefault Note ToDo + +# Java language specification cite +JLS3_CITE = <a href=\"$(JLS3_URL)\"> \ + The Java Language Specification, Third Edition</a> +TAG_JLS3 = -tag 'jls3:a:See <cite>$(JLS3_CITE)</cite>:' + +TAGS = $(IGNORED_TAGS:%=-tag %:X) $(TAG_JLS3) + +# Overview file for core apis +COREAPI_OVERVIEW = $(SHARE_SRC)/classes/overview-core.html + +# The index.html, options, and packages files +COREAPI_INDEX_FILE = $(COREAPI_DOCSDIR)/index.html +COREAPI_OPTIONS_FILE = $(DOCSTMPDIR)/coredocs.options +COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages + +coredocs: $(COREAPI_INDEX_FILE) + +# Set relative location to core api document root +$(COREAPI_INDEX_FILE): GET2DOCSDIR=.. -.PHONY: rel-docs -rel-docs: rel-coredocs ${ALL_OTHER_TARGETS} +# Run javadoc if the index file is out of date or missing +$(COREAPI_INDEX_FILE): $(COREAPI_OPTIONS_FILE) $(COREAPI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(COREAPI_OPTIONS_FILE),$(COREAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(COREAPI_OPTIONS_FILE) @$(COREAPI_PACKAGES_FILE) + +# Create file with javadoc options in it +$(COREAPI_OPTIONS_FILE): $(COREAPI_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "$(TAGS)" ; \ + $(ECHO) "-encoding ISO-8859-1" ; \ + $(ECHO) "-splitIndex" ; \ + $(ECHO) "-overview $(COREAPI_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(COREAPI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(COREAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(COREAPI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(COREAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + ) >> $@ +ifdef COREAPI_TOP_EARLYACCESS + @$(ECHO) "-top '$(COREAPI_TOP_EARLYACCESS)'" >> $@ +endif + +# Create a file with the package names in it +$(COREAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(CORE_PKGS)) + $(prep-target) + $(call PackageFilter,$(CORE_PKGS)) + +############################################################# # -# end of production targets -############################################################# +# mirrordocs +# + +# Part of langtools +ifdef LANGTOOLS_DIST + ALL_OTHER_TARGETS += mirrordocs +endif -.PHONY: coredocs -coredocs: - @# ######## core packages ####################### - $(RM) -r $(DOCSDIR)/api - $(MKDIR) -p $(DOCSDIR)/api - $(JAVADOC_CMD) $(CORE_JAVADOCFLAGS) \ - -d $(DOCSDIR)/api \ - -sourcepath $(RELEASEDOCS_SRCPATH) \ - $(CORE_PKGS) +MIRROR_DOCDIR := $(JDK_API_DOCSDIR)/apt/mirror +MIRROR2COREAPI := ../../$(JDKJRE2COREAPI) +MIRROR_DOCTITLE := Mirror API +MIRROR_WINDOWTITLE := Mirror API +MIRROR_HEADER := <strong>Mirror API</strong> +MIRROR_BOTTOM := $(call CommonBottom,$(MIRROR_FIRST_COPYRIGHT_YEAR)) +MIRROR_GROUPNAME := Packages +MIRROR_OVERVIEW := $(IMPORTSRCDIR)/com/sun/mirror/overview.html +MIRROR_REGEXP := com.sun.mirror.* +# MIRROR_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +MIRROR_INDEX_FILE = $(MIRROR_DOCDIR)/index.html +MIRROR_OPTIONS_FILE = $(DOCSTMPDIR)/mirror.options +MIRROR_PACKAGES_FILE = $(DOCSTMPDIR)/mirror.packages + +mirrordocs: $(MIRROR_INDEX_FILE) + +# Set relative location to core api document root +$(MIRROR_INDEX_FILE): GET2DOCSDIR=$(MIRROR2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(MIRROR_INDEX_FILE): $(MIRROR_OPTIONS_FILE) $(MIRROR_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(MIRROR_OPTIONS_FILE),$(MIRROR_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(MIRROR_OPTIONS_FILE) @$(MIRROR_PACKAGES_FILE) -.PHONY: mirrordocs -mirrordocs: - @# ######## mirror api for apt ################## - $(RM) -r $(MIRROR_DESTDIR) - $(MKDIR) -p $(MIRROR_DESTDIR) - $(JAVADOC_CMD) $(MIRROR_JAVADOCFLAGS) \ - -d $(MIRROR_DESTDIR) \ - -sourcepath $(RELEASEDOCS_SRCPATH) \ - $(MIRROR_LINKOPT) \ - $(MIRROR_PKGS) +# Create file with javadoc options in it +$(MIRROR_OPTIONS_FILE): $(MIRROR_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-overview $(MIRROR_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(MIRROR_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(MIRROR_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(MIRROR_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(MIRROR_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-group $(MIRROR_GROUPNAME) $(MIRROR_REGEXP)" ; \ + $(ECHO) "-linkoffline $(MIRROR2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ + +# Create a file with the package names in it +$(MIRROR_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MIRROR_PKGS)) + $(prep-target) + $(call PackageFilter,$(MIRROR_PKGS)) + +############################################################# +# +# docletapidocs +# + +# Part of langtools +ifdef LANGTOOLS_DIST + ALL_OTHER_TARGETS += docletapidocs +endif + +DOCLETAPI_DOCDIR := $(JDK_API_DOCSDIR)/javadoc/doclet +DOCLETAPI2COREAPI := ../../$(JDKJRE2COREAPI) +DOCLETAPI_DOCTITLE := Doclet API +DOCLETAPI_WINDOWTITLE := Doclet API +DOCLETAPI_HEADER := <strong>Doclet API</strong> +DOCLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOCLETAPI_FIRST_COPYRIGHT_YEAR)) +DOCLETAPI_GROUPNAME := Packages +DOCLETAPI_REGEXP := com.sun.javadoc +# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +DOCLETAPI_INDEX_FILE = $(DOCLETAPI_DOCDIR)/index.html +DOCLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/docletapi.options +DOCLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/docletapi.packages + +docletapidocs: $(DOCLETAPI_INDEX_FILE) -.PHONY: docletapidocs -docletapidocs: - @# ######## doclet api ############################ - $(RM) -r $(DOCSDIR)/jdk/api/javadoc/doclet - $(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/doclet - $(JAVADOC_CMD) $(DOCLETAPI_JAVADOCFLAGS) \ - -d $(DOCSDIR)/jdk/api/javadoc/doclet \ - -sourcepath $(RELEASEDOCS_SRCPATH) \ - $(DOCLETAPI_LINKOPT) \ - $(DOCLETAPI_PKGS) +# Set relative location to core api document root +$(DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(DOCLETAPI2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(DOCLETAPI_OPTIONS_FILE),$(DOCLETAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(DOCLETAPI_OPTIONS_FILE) @$(DOCLETAPI_PACKAGES_FILE) + +# Create file with javadoc options in it +$(DOCLETAPI_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-breakiterator" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-doctitle '$(DOCLETAPI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(DOCLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(DOCLETAPI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(DOCLETAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-group $(DOCLETAPI_GROUPNAME) $(DOCLETAPI_REGEXP)" ; \ + $(ECHO) "-linkoffline $(DOCLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ + +# Create a file with the package names in it +$(DOCLETAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOCLETAPI_PKGS)) + $(prep-target) + $(call PackageFilter,$(DOCLETAPI_PKGS)) + +############################################################# +# +# tagletapidocs +# + +# Part of langtools +ifdef LANGTOOLS_DIST + ALL_OTHER_TARGETS += tagletapidocs +endif + +TAGLETAPI_DOCDIR := $(JDK_API_DOCSDIR)/javadoc/taglet +TAGLETAPI2COREAPI := ../../$(JDKJRE2COREAPI) +TAGLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(TAGLETAPI_FIRST_COPYRIGHT_YEAR)) +# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk + +# Temporary directory (special generation rules) +TAGLETAPI_TEMPDIR = $(DOCSTMPDIR)/taglets_temp + +# The index.html, options, and packages files +TAGLETAPI_INDEX_FILE = $(TAGLETAPI_DOCDIR)/index.html +TAGLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/tagletapi.options +TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages + +tagletapidocs: $(TAGLETAPI_INDEX_FILE) + +# Set relative location to core api document root +$(TAGLETAPI_INDEX_FILE): GET2DOCSDIR=$(TAGLETAPI2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE) + $(prep-javadoc) + $(RM) -r $(TAGLETAPI_TEMPDIR) + $(MKDIR) -p $(TAGLETAPI_TEMPDIR) + $(call JavadocSummary,$(TAGLETAPI_OPTIONS_FILE),$(TAGLETAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(TAGLETAPI_TEMPDIR) \ + @$(TAGLETAPI_OPTIONS_FILE) @$(TAGLETAPI_PACKAGES_FILE) + cp -r $(TAGLETAPI_TEMPDIR)/com $(@D) + cp $(TAGLETAPI_TEMPDIR)/stylesheet.css $(@D) + $(RM) -r $(TAGLETAPI_TEMPDIR) -.PHONY: tagletapidocs -tagletapidocs: - @# ######## taglet api ############################ - $(RM) -r $(DOCSDIR)/jdk/api/javadoc/taglet - $(MKDIR) -p $(DOCSDIR)/jdk/api/javadoc/taglet - $(RM) -r $(DOCSTMPDIR) - $(MKDIR) -p $(DOCSTMPDIR) - $(JAVADOC_CMD) $(TAGLETAPI_JAVADOCFLAGS) \ - -d $(DOCSTMPDIR) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ \ - $(IMPORTSRCDIR)/$(TAGLETAPI_FILE) - cp -r $(DOCSTMPDIR)/com $(DOCSDIR)/jdk/api/javadoc/taglet - cp $(DOCSTMPDIR)/stylesheet.css $(DOCSDIR)/jdk/api/javadoc/taglet - $(RM) -r $(DOCSTMPDIR) +# Create file with javadoc options in it +$(TAGLETAPI_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nonavbar" ; \ + $(ECHO) "-noindex" ; \ + $(ECHO) "-bottom '$(TAGLETAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(TAGLETAPI2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ + +# Create a file with the package names in it +$(TAGLETAPI_PACKAGES_FILE): $(IMPORTSRCDIR)/$(TAGLETAPI_FILE) + $(prep-target) + @($(ECHO) "$(IMPORTSRCDIR)/$(TAGLETAPI_FILE)" ) > $@ + +############################################################# +# +# domapidocs +# + +ALL_OTHER_TARGETS += domapidocs + +DOMAPI_DOCDIR := $(JRE_API_DOCSDIR)/plugin/dom +DOMAPI2COREAPI := ../../$(JDKJRE2COREAPI) +DOMAPI_DOCTITLE := Common DOM API +DOMAPI_WINDOWTITLE := Common DOM API +DOMAPI_HEADER := <strong>Common DOM API</strong> +DOMAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOMAPI_FIRST_COPYRIGHT_YEAR)) +DOMAPI_GROUPNAME := Packages +DOMAPI_REGEXP := com.sun.java.browser.dom:org.w3c.dom* +# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +DOMAPI_INDEX_FILE = $(DOMAPI_DOCDIR)/index.html +DOMAPI_OPTIONS_FILE = $(DOCSTMPDIR)/domapi.options +DOMAPI_PACKAGES_FILE = $(DOCSTMPDIR)/domapi.packages -.PHONY: domapidocs -domapidocs: - @# ######## dom api ############################ - $(RM) -r $(DOCSDIR)/jre/api/plugin/dom - $(MKDIR) -p $(DOCSDIR)/jre/api/plugin/dom - $(JAVADOC_CMD) $(DOMAPI_JAVADOCFLAGS) \ - -d $(DOCSDIR)/jre/api/plugin/dom \ - -sourcepath $(RELEASEDOCS_SRCPATH) \ - -linkoffline ../../../../api $(DOCSDIR)/api/ \ - $(DOMAPI_PKGS) +domapidocs: $(DOMAPI_INDEX_FILE) + +# Set relative location to core api document root +$(DOMAPI_INDEX_FILE): GET2DOCSDIR=$(DOMAPI2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(DOMAPI_OPTIONS_FILE),$(DOMAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(DOMAPI_OPTIONS_FILE) @$(DOMAPI_PACKAGES_FILE) -.PHONY: jpdadocs +# Create file with javadoc options in it +$(DOMAPI_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-splitIndex" ; \ + $(ECHO) "-doctitle '$(DOMAPI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(DOMAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(DOMAPI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(DOMAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-group $(DOMAPI_GROUPNAME) $(DOMAPI_REGEXP)" ; \ + $(ECHO) "-linkoffline $(DOMAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(DOMAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(DOMAPI_PKGS)) + $(prep-target) + $(call PackageFilter,$(DOMAPI_PKGS)) + +############################################################# +# +# jpdadocs +# + +ALL_OTHER_TARGETS += jpdadocs + jpdadocs: jdidocs jdwpdocs jvmtidocs -.PHONY: jdidocs -jdidocs: - @# ######## jdi ################################# - $(RM) -r $(DOCSDIR)/jdk/api/jpda/jdi - $(MKDIR) -p $(DOCSDIR)/jdk/api/jpda/jdi - $(JAVADOC_CMD) $(JDI_JAVADOCFLAGS) \ - $(JDI_PKGS) +############################################################# +# +# jdidocs +# + +ALL_OTHER_TARGETS += jdidocs + +JDI_DOCDIR := $(JDK_API_DOCSDIR)/jpda/jdi +JDI2COREAPI := ../../$(JDKJRE2COREAPI) +JDI_DOCTITLE := Java$(TRADEMARK) Debug Interface +JDI_WINDOWTITLE := Java Debug Interface +JDI_HEADER := <strong>Java Debug Interface</strong> +JDI_BOTTOM := $(call CommonBottom,$(JDI_FIRST_COPYRIGHT_YEAR)) +JDI_OVERVIEW := $(SHARE_SRC)/classes/jdi-overview.html +# JDI_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +JDI_INDEX_FILE = $(JDI_DOCDIR)/index.html +JDI_OPTIONS_FILE = $(DOCSTMPDIR)/jdi.options +JDI_PACKAGES_FILE = $(DOCSTMPDIR)/jdi.packages + +jdidocs: $(JDI_INDEX_FILE) + +# Set relative location to core api document root +$(JDI_INDEX_FILE): GET2DOCSDIR=$(JDI2COREAPI)/.. +# Run javadoc if the index file is out of date or missing +$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(JDI_OPTIONS_FILE),$(JDI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(JDI_OPTIONS_FILE) @$(JDI_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JDI_OPTIONS_FILE): $(JDI_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-overview $(JDI_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(JDI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(JDI_WINDOWTITLE) $(DRAFT_WINTITLE)'" ; \ + $(ECHO) "-header '$(JDI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(JDI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(JDI2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(JDI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JDI_PKGS)) + $(prep-target) + $(call PackageFilter,$(JDI_PKGS)) + +############################################################# +# +# jdwpdocs +# + +ALL_OTHER_TARGETS += jdwpdocs + +JDWP_DOCDIR = $(PLATFORM_DOCSDIR)/jpda/jdwp JDWP_SPEC = $(BUILDDIR)/jpda/jdwp/jdwp.spec -JDWP_DOC = $(DOCSDIR)/platform/jpda/jdwp/jdwp-protocol.html JDWPGEN_JARFILE = $(BUILDTOOLJARDIR)/jdwpgen.jar -.PHONY: jdwpdocs -jdwpdocs: $(JDWP_DOC) +jdwpdocs: $(JDWP_DOCDIR)/jdwp-protocol.html +$(JDWP_DOCDIR)/jdwp-protocol.html: $(JDWPGEN_JARFILE) $(JDWP_SPEC) + $(prep-javadoc) + $(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $@ -$(JDWP_DOC): $(JDWPGEN_JARFILE) $(JDWP_SPEC) - $(prep-target) - $(BOOT_JAVA_CMD) -jar $(JDWPGEN_JARFILE) $(JDWP_SPEC) -doc $(JDWP_DOC) +############################################################# +# +# jvmtidocs +# + +ALL_OTHER_TARGETS += jvmtidocs -.PHONY: jvmtidocs -jvmtidocs: - @# ######## jvmti ################################# - @if [ -f $(JVMTI_HTML) ] ; then \ - $(RM) -r $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \ - $(MKDIR) -p $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \ - $(ECHO) $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \ - $(CP) $(JVMTI_HTML) $(DOCSDIR)/$(JVMTI_DOCS_SUBDIR); \ - else \ - $(ECHO) "WARNING: Generated jvmti file does not exist: $(JVMTI_HTML)"; \ +JVMTI_DOCDIR = $(PLATFORM_DOCSDIR)/jvmti +JVMTI_HTML = $(HOTSPOT_DOCS_IMPORT_PATH)/platform/jvmti/jvmti.html + +jvmtidocs: $(JVMTI_DOCDIR)/jvmti.html +$(JVMTI_DOCDIR)/jvmti.html: + @$(prep-javadoc) + @if [ -f $(JVMTI_HTML) ] ; then \ + $(ECHO) "$(CP) $(JVMTI_HTML) $@"; \ + $(CP) $(JVMTI_HTML) $@; \ + else \ + $(ECHO) "WARNING: Generated file does not exist: $(JVMTI_HTML)"; \ fi -.PHONY: jaasdocs -jaasdocs: - @# ######## api-jaas ############################ - $(RM) -r $(JAAS_DOCDIR) - $(MKDIR) -p $(JAAS_DOCDIR) - $(JAVADOC_CMD) $(JAAS_JAVADOCFLAGS) \ - $(JAAS_PKGS) +############################################################# +# +# jaasdocs +# + +ALL_OTHER_TARGETS += jaasdocs + +JAAS_DOCDIR := $(JRE_API_DOCSDIR)/security/jaas/spec +JAAS2COREAPI := ../../../$(JDKJRE2COREAPI) +JAAS_DOCTITLE := Java$(TRADEMARK) Authentication and Authorization Service +JAAS_WINDOWTITLE := Java Authentication and Authorization Service +JAAS_HEADER := <strong>Java Authentication and Authorization Service</strong> +JAAS_BOTTOM := $(call CommonBottom,$(JAAS_FIRST_COPYRIGHT_YEAR)) +# JAAS_PKGS is located in NON_CORE_PKGS.gmk +JAAS_OVERVIEW := $(SHARE_SRC)/classes/com/sun/security/auth/jaas-overview.html + +# The index.html, options, and packages files +JAAS_INDEX_FILE = $(JAAS_DOCDIR)/index.html +JAAS_OPTIONS_FILE = $(DOCSTMPDIR)/jaas.options +JAAS_PACKAGES_FILE = $(DOCSTMPDIR)/jaas.packages + +jaasdocs: $(JAAS_INDEX_FILE) + +# Set relative location to core api document root +$(JAAS_INDEX_FILE): GET2DOCSDIR=$(JAAS2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(JAAS_OPTIONS_FILE),$(JAAS_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(JAAS_OPTIONS_FILE) @$(JAAS_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JAAS_OPTIONS_FILE): $(JAAS_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-overview $(JAAS_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(JAAS_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(JAAS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \ + $(ECHO) "-header '$(JAAS_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(JAAS_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(JAAS2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(JAAS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JAAS_PKGS)) + $(prep-target) + $(call PackageFilter,$(JAAS_PKGS)) + +############################################################# +# +# jgssdocs +# + +ALL_OTHER_TARGETS += jgssdocs + +JGSS_DOCDIR := $(JRE_API_DOCSDIR)/security/jgss/spec +JGSS2COREAPI := ../../../$(JDKJRE2COREAPI) +JGSS_DOCTITLE := Java$(TRADEMARK) GSS-API Utilities +JGSS_WINDOWTITLE := Java GSS-API Utilities +JGSS_HEADER := <strong>Java GSS-API Utilities</strong> +JGSS_BOTTOM := $(call CommonBottom,$(JGSS_FIRST_COPYRIGHT_YEAR)) +JGSS_OVERVIEW := $(SHARE_SRC)/classes/com/sun/security/jgss/jgss-overview.html +# JGSS_PKGS is located in NON_CORE_PKGS.gmk -.PHONY: jgssdocs -jgssdocs: - @# ######## api-jgss ############################ - $(RM) -r $(JGSS_DOCDIR) - $(MKDIR) -p $(JGSS_DOCDIR) - $(JAVADOC_CMD) $(JGSS_JAVADOCFLAGS) \ - $(JGSS_PKGS) +# The index.html, options, and packages files +JGSS_INDEX_FILE = $(JGSS_DOCDIR)/index.html +JGSS_OPTIONS_FILE = $(DOCSTMPDIR)/jgss.options +JGSS_PACKAGES_FILE = $(DOCSTMPDIR)/jgss.packages + +jgssdocs: $(JGSS_INDEX_FILE) + +# Set relative location to core api document root +$(JGSS_INDEX_FILE): GET2DOCSDIR=$(JGSS2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(JGSS_OPTIONS_FILE),$(JGSS_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(JGSS_OPTIONS_FILE) @$(JGSS_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JGSS_OPTIONS_FILE): $(JGSS_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-overview $(JGSS_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(JGSS_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(JGSS_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \ + $(ECHO) "-header '$(JGSS_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(JGSS_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(JGSS2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(JGSS_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JGSS_PKGS)) + $(prep-target) + $(call PackageFilter,$(JGSS_PKGS)) + +############################################################# +# +# smartcardiodocs +# + +ALL_OTHER_TARGETS += smartcardiodocs + +SMARTCARDIO_DOCDIR := $(JRE_API_DOCSDIR)/security/smartcardio/spec +SMARTCARDIO2COREAPI := ../../../$(JDKJRE2COREAPI) +SMARTCARDIO_DOCTITLE := Java$(TRADEMARK) Smart Card I/O +SMARTCARDIO_WINDOWTITLE := Java Smart Card I/O +SMARTCARDIO_HEADER := <strong>Java Smart Card I/O</strong> +SMARTCARDIO_BOTTOM := $(call CommonBottom,$(SMARTCARDIO_FIRST_COPYRIGHT_YEAR)) +# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +SMARTCARDIO_INDEX_FILE = $(SMARTCARDIO_DOCDIR)/index.html +SMARTCARDIO_OPTIONS_FILE = $(DOCSTMPDIR)/smartcardio.options +SMARTCARDIO_PACKAGES_FILE = $(DOCSTMPDIR)/smartcardio.packages + +smartcardiodocs: $(SMARTCARDIO_INDEX_FILE) + +# Set relative location to core api document root +$(SMARTCARDIO_INDEX_FILE): GET2DOCSDIR=$(SMARTCARDIO2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(SMARTCARDIO_OPTIONS_FILE),$(SMARTCARDIO_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(SMARTCARDIO_OPTIONS_FILE) @$(SMARTCARDIO_PACKAGES_FILE) -.PHONY: smartcardiodocs -smartcardiodocs: - @# ######## api-smartcardio ############################ - $(RM) -r $(SMARTCARDIO_DOCDIR) - $(MKDIR) -p $(SMARTCARDIO_DOCDIR) - $(JAVADOC_CMD) $(SMARTCARDIO_JAVADOCFLAGS) \ - $(SMARTCARDIO_PKGS) +# Create file with javadoc options in it +$(SMARTCARDIO_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(SMARTCARDIO_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(SMARTCARDIO_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(SMARTCARDIO_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(SMARTCARDIO_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(SMARTCARDIO2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ + +# Create a file with the package names in it +$(SMARTCARDIO_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SMARTCARDIO_PKGS)) + $(prep-target) + $(call PackageFilter,$(SMARTCARDIO_PKGS)) + +############################################################# +# +# httpserverdocs +# + +ALL_OTHER_TARGETS += httpserverdocs + +HTTPSERVER_DOCDIR := $(JRE_API_DOCSDIR)/net/httpserver/spec +HTTPSERVER2COREAPI := ../../../$(JDKJRE2COREAPI) +HTTPSERVER_DOCTITLE := Java$(TRADEMARK) HTTP Server +HTTPSERVER_WINDOWTITLE := Java HTTP Server +HTTPSERVER_HEADER := <strong>Java HTTP Server</strong> +HTTPSERVER_BOTTOM := $(call CommonBottom,$(HTTPSERVER_FIRST_COPYRIGHT_YEAR)) +# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk + +HTTPSERVER_INDEX_HTML = $(HTTPSERVER_DOCDIR)/index.html +HTTPSERVER_OPTIONS_FILE = $(DOCSTMPDIR)/httpserver.options +HTTPSERVER_PACKAGES_FILE = $(DOCSTMPDIR)/httpserver.packages + +httpserverdocs: $(HTTPSERVER_INDEX_HTML) + +# Set relative location to core api document root +$(HTTPSERVER_INDEX_HTML): GET2DOCSDIR=$(HTTPSERVER2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(HTTPSERVER_OPTIONS_FILE),$(HTTPSERVER_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(HTTPSERVER_OPTIONS_FILE) @$(HTTPSERVER_PACKAGES_FILE) + +# Create file with javadoc options in it +$(HTTPSERVER_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(HTTPSERVER_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(HTTPSERVER_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(HTTPSERVER_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(HTTPSERVER_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(HTTPSERVER2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ -.PHONY: tracingdocs -tracingdocs: - @# ######## api-tracing ############################ - $(RM) -r $(TRACING_DOCDIR) - $(MKDIR) -p $(TRACING_DOCDIR) - $(JAVADOC_CMD) $(TRACING_JAVADOCFLAGS) \ - $(TRACING_PKGS) +# Create a file with the package names in it +$(HTTPSERVER_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(HTTPSERVER_PKGS)) + $(prep-target) + $(call PackageFilter,$(HTTPSERVER_PKGS)) + +############################################################# +# +# mgmtdocs +# + +ALL_OTHER_TARGETS += mgmtdocs + +MGMT_DOCDIR := $(JRE_API_DOCSDIR)/management/extension +MGMT2COREAPI := ../../$(JDKJRE2COREAPI) +JVM_MIB_NAME := JVM-MANAGEMENT-MIB.mib +JVM_MIB_SRC := $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME) +MGMT_DOCTITLE := Monitoring and Management Interface for the Java$(TRADEMARK) Platform +MGMT_WINDOWTITLE := Monitoring and Management Interface for the Java Platform +MGMT_HEADER := <strong>Monitoring and Management Interface for the Java Platform</strong> +MGMT_BOTTOM := $(call CommonBottom,$(MGMT_FIRST_COPYRIGHT_YEAR)) +MGMT_OVERVIEW := $(SHARE_SRC)/classes/com/sun/management/mgmt-overview.html +# MGMT_PKGS is located in NON_CORE_PKGS.gmk + +# The index.html, options, and packages files +MGMT_INDEX_FILE = $(MGMT_DOCDIR)/index.html +MGMT_OPTIONS_FILE = $(DOCSTMPDIR)/mgmt.options +MGMT_PACKAGES_FILE = $(DOCSTMPDIR)/mgmt.packages + +mgmtdocs: $(MGMT_INDEX_FILE) + +# Set relative location to core api document root +$(MGMT_INDEX_FILE): GET2DOCSDIR=$(MGMT2COREAPI)/.. -.PHONY: httpserverdocs -httpserverdocs: - @# ######## api-httpserver ####################### - $(RM) -r $(HTTPSERVER_DOCDIR) - $(MKDIR) -p $(HTTPSERVER_DOCDIR) - $(JAVADOC_CMD) $(HTTPSERVER_JAVADOCFLAGS) \ - $(HTTPSERVER_PKGS) +# Run javadoc if the index file is out of date or missing +$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE) + $(prep-javadoc) + @if [ -f $(JVM_MIB_SRC) ] ; then \ + $(ECHO) "$(CP) $(JVM_MIB_SRC) $(@D)/.."; \ + $(CP) $(JVM_MIB_SRC) $(@D)/.. ; \ + else \ + $(ECHO) "WARNING: File $(JVM_MIB_NAME) not available."; \ + fi + $(call JavadocSummary,$(MGMT_OPTIONS_FILE),$(MGMT_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(MGMT_OPTIONS_FILE) @$(MGMT_PACKAGES_FILE) + +# Create file with javadoc options in it +$(MGMT_OPTIONS_FILE): $(MGMT_OVERVIEW) + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-overview $(MGMT_OVERVIEW)" ; \ + $(ECHO) "-doctitle '$(MGMT_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(MGMT_WINDOWTITLE) $(DRAFT_WINTITLE)'"; \ + $(ECHO) "-header '$(MGMT_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(MGMT_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(MGMT2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(MGMT_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(MGMT_PKGS)) + $(prep-target) + $(call PackageFilter,$(MGMT_PKGS)) + +############################################################# +# +# attachdocs +# + +ALL_OTHER_TARGETS += attachdocs -.PHONY: sctpdocs -sctpdocs: - @# ######## api-sctp ####################### - $(RM) -r $(SCTPAPI_DOCDIR) - $(MKDIR) -p $(SCTPAPI_DOCDIR) - $(JAVADOC_CMD) $(SCTPAPI_JAVADOCFLAGS) \ - $(SCTPAPI_PKGS) +ATTACH_DOCDIR := $(JDK_API_DOCSDIR)/attach/spec +ATTACH2COREAPI := ../../$(JDKJRE2COREAPI) +ATTACH_DOCTITLE := Attach API +ATTACH_WINDOWTITLE := Attach API +ATTACH_HEADER := <strong>Attach API</strong> +ATTACH_BOTTOM := $(call CommonBottom,$(ATTACH_FIRST_COPYRIGHT_YEAR)) +# ATTACH_PKGS is located in NON_CORE_PKGS.gmk + +ATTACH_INDEX_HTML = $(ATTACH_DOCDIR)/index.html +ATTACH_OPTIONS_FILE = $(DOCSTMPDIR)/attach.options +ATTACH_PACKAGES_FILE = $(DOCSTMPDIR)/attach.packages + +attachdocs: $(ATTACH_INDEX_HTML) + +# Set relative location to core api document root +$(ATTACH_INDEX_HTML): GET2DOCSDIR=$(ATTACH2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(ATTACH_OPTIONS_FILE),$(ATTACH_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(ATTACH_OPTIONS_FILE) @$(ATTACH_PACKAGES_FILE) + +# Create file with javadoc options in it +$(ATTACH_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(ATTACH_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(ATTACH_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(ATTACH_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(ATTACH_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(ATTACH2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(ATTACH_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(ATTACH_PKGS)) + $(prep-target) + $(call PackageFilter,$(ATTACH_PKGS)) + +############################################################# +# +# jconsoledocs +# + +ALL_OTHER_TARGETS += jconsoledocs + +JCONSOLE_DOCDIR := $(JDK_API_DOCSDIR)/jconsole/spec +JCONSOLE2COREAPI := ../../$(JDKJRE2COREAPI) +JCONSOLE_DOCTITLE := JConsole API +JCONSOLE_WINDOWTITLE := JConsole API +JCONSOLE_HEADER := <strong>JConsole API</strong> +JCONSOLE_BOTTOM := $(call CommonBottom,$(JCONSOLE_FIRST_COPYRIGHT_YEAR)) +# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk + +JCONSOLE_INDEX_HTML = $(JCONSOLE_DOCDIR)/index.html +JCONSOLE_OPTIONS_FILE = $(DOCSTMPDIR)/jconsole.options +JCONSOLE_PACKAGES_FILE = $(DOCSTMPDIR)/jconsole.packages + +jconsoledocs: $(JCONSOLE_INDEX_HTML) -.PHONY: mgmtdocs -mgmtdocs: $(COPY-MIB-TARGET) - @# ######## api-management ############################ - $(RM) -r $(MGMT_EXT_DIR) - $(MKDIR) -p $(MGMT_EXT_DIR) - $(JAVADOC_CMD) $(MGMT_JAVADOCFLAGS) \ - $(MGMT_PKGS) +# Set relative location to core api document root +$(JCONSOLE_INDEX_HTML): GET2DOCSDIR=$(JCONSOLE2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(JCONSOLE_OPTIONS_FILE),$(JCONSOLE_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(JCONSOLE_OPTIONS_FILE) @$(JCONSOLE_PACKAGES_FILE) + +# Create file with javadoc options in it +$(JCONSOLE_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(JCONSOLE_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(JCONSOLE_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(JCONSOLE_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(JCONSOLE_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(JCONSOLE2COREAPI) $(COREAPI_DOCSDIR)/"; \ + ) >> $@ + +# Create a file with the package names in it +$(JCONSOLE_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(JCONSOLE_PKGS)) + $(prep-target) + $(call PackageFilter,$(JCONSOLE_PKGS)) -copy-mib: - @# ######## copy-snmp-mib ############################ - $(RM) $(MGMT_DOCDIR)/$(JVM_MIB_NAME) - $(MKDIR) -p $(MGMT_DOCDIR) - $(CP) $(JVM_MIB_SRC) $(MGMT_DOCDIR) +############################################################# +# +# treeapidocs +# + +# Part of langtools +ifdef LANGTOOLS_DIST + ALL_OTHER_TARGETS += treeapidocs +endif + +TREEAPI_DOCDIR := $(JDK_API_DOCSDIR)/javac/tree +TREEAPI2COREAPI := ../../$(JDKJRE2COREAPI) +TREEAPI_DOCTITLE := Compiler Tree API +TREEAPI_WINDOWTITLE := Compiler Tree API +TREEAPI_HEADER := <strong>Compiler Tree API</strong> +TREEAPI_BOTTOM := $(call CommonBottom,$(TREEAPI_FIRST_COPYRIGHT_YEAR)) +TREEAPI_GROUPNAME := Packages +TREEAPI_REGEXP := com.sun.source.* +# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk + +TREEAPI_INDEX_HTML = $(TREEAPI_DOCDIR)/index.html +TREEAPI_OPTIONS_FILE = $(DOCSTMPDIR)/treeapi.options +TREEAPI_PACKAGES_FILE = $(DOCSTMPDIR)/treeapi.packages + +treeapidocs: $(TREEAPI_INDEX_HTML) + +# Set relative location to core api document root +$(TREEAPI_INDEX_HTML): GET2DOCSDIR=$(TREEAPI2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(TREEAPI_OPTIONS_FILE),$(TREEAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(TREEAPI_OPTIONS_FILE) @$(TREEAPI_PACKAGES_FILE) -.PHONY: attachdocs -attachdocs: - @# ######## api-attach ############################ - $(RM) -r $(ATTACH_DOCDIR) - $(MKDIR) -p $(ATTACH_DOCDIR) - $(JAVADOC_CMD) $(ATTACH_JAVADOCFLAGS) \ - $(ATTACH_PKGS) +# Create file with javadoc options in it +$(TREEAPI_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-doctitle '$(TREEAPI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(TREEAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(TREEAPI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(TREEAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-group $(TREEAPI_GROUPNAME) $(TREEAPI_REGEXP)" ; \ + $(ECHO) "-linkoffline $(TREEAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(TREEAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TREEAPI_PKGS)) + $(prep-target) + $(call PackageFilter,$(TREEAPI_PKGS)) + +############################################################# +# +# sctpdocs +# + +ALL_OTHER_TARGETS += sctpdocs + +SCTPAPI_DOCDIR := $(JRE_API_DOCSDIR)/nio/sctp/spec +SCTPAPI2COREAPI := ../../../$(JDKJRE2COREAPI) +SCTPAPI_DOCTITLE := SCTP API +SCTPAPI_WINDOWTITLE := SCTP API +SCTPAPI_HEADER := <strong>SCTP API</strong> +SCTPAPI_BOTTOM := $(call CommonBottom,$(SCTPAPI_FIRST_COPYRIGHT_YEAR)) +# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk + +SCTPAPI_INDEX_HTML = $(SCTPAPI_DOCDIR)/index.html +SCTPAPI_OPTIONS_FILE = $(DOCSTMPDIR)/sctp.options +SCTPAPI_PACKAGES_FILE = $(DOCSTMPDIR)/sctp.packages + +sctpdocs: $(SCTPAPI_INDEX_HTML) + +# Set relative location to core api document root +$(SCTSCTSCTP: GET2DOCSDIR=$(SCTPAPI2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(SCTPAPI_OPTIONS_FILE),$(SCTPAPI_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(SCTPAPI_OPTIONS_FILE) @$(SCTPAPI_PACKAGES_FILE) + +# Create file with javadoc options in it +$(SCTPAPI_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(SCTPAPI_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(SCTPAPI_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(SCTPAPI_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(SCTPAPI_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(SCTPAPI2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(SCTPAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(SCTPAPI_PKGS)) + $(prep-target) + $(call PackageFilter,$(SCTPAPI_PKGS)) + +############################################################# +# +# tracingdocs +# -.PHONY: jconsoledocs -jconsoledocs: - @# ######## api-jconsole ############################ - $(RM) -r $(JCONSOLE_DOCDIR) - $(MKDIR) -p $(JCONSOLE_DOCDIR) - $(JAVADOC_CMD) $(JCONSOLE_JAVADOCFLAGS) \ - $(JCONSOLE_PKGS) +ALL_OTHER_TARGETS += tracingdocs + +TRACING_DOCDIR := $(JRE_API_DOCSDIR)/tracing +TRACING2COREAPI := ../$(JDKJRE2COREAPI) +TRACING_DOCTITLE := Java$(TRADEMARK) Platform Tracing +TRACING_WINDOWTITLE := Platform Tracing +TRACING_HEADER := <strong>Platform Tracing</strong> +TRACING_BOTTOM := $(call CommonBottom,$(TRACING_FIRST_COPYRIGHT_YEAR)) +# TRACING_PKGS is located in NON_CORE_PKGS.gmk + +TRACING_INDEX_HTML = $(TRACING_DOCDIR)/index.html +TRACING_OPTIONS_FILE = $(DOCSTMPDIR)/tracing.options +TRACING_PACKAGES_FILE = $(DOCSTMPDIR)/tracing.packages + +tracingdocs: $(TRACING_INDEX_HTML) + +# Set relative location to core api document root +$(TRACING_INDEX_HTML): GET2DOCSDIR=$(TRACING2COREAPI)/.. + +# Run javadoc if the index file is out of date or missing +$(TRACING_INDEX_HTML): $(TRACING_OPTIONS_FILE) $(TRACING_PACKAGES_FILE) + $(prep-javadoc) + $(call JavadocSummary,$(TRACING_OPTIONS_FILE),$(TRACING_PACKAGES_FILE)) + $(JAVADOC_CMD) $(JAVADOC_VM_MEMORY_FLAGS) -d $(@D) \ + @$(TRACING_OPTIONS_FILE) @$(TRACING_PACKAGES_FILE) -.PHONY: treeapidocs -treeapidocs: - @# ######## tree api for javac ################## - $(RM) -r $(TREEAPI_DESTDIR) - $(MKDIR) -p $(TREEAPI_DESTDIR) - $(JAVADOC_CMD) $(TREEAPI_JAVADOCFLAGS) \ - -d $(TREEAPI_DESTDIR) \ - -sourcepath $(RELEASEDOCS_SRCPATH) \ - $(TREEAPI_LINKOPT) \ - $(TREEAPI_PKGS) +# Create file with javadoc options in it +$(TRACING_OPTIONS_FILE): + $(prep-target) + @($(ECHO) "$(COMMON_JAVADOCFLAGS)" ; \ + $(ECHO) "-sourcepath \"$(RELEASEDOCS_SOURCEPATH)\"" ; \ + $(ECHO) "-encoding ascii" ; \ + $(ECHO) "-nodeprecatedlist" ; \ + $(ECHO) "-doctitle '$(TRACING_DOCTITLE)'" ; \ + $(ECHO) "-windowtitle '$(TRACING_WINDOWTITLE) $(DRAFT_WINTITLE)'";\ + $(ECHO) "-header '$(TRACING_HEADER)$(DRAFT_HEADER)'" ; \ + $(ECHO) "-bottom '$(TRACING_BOTTOM)$(DRAFT_BOTTOM)'" ; \ + $(ECHO) "-linkoffline $(TRACING2COREAPI) $(COREAPI_DOCSDIR)/" ; \ + ) >> $@ + +# Create a file with the package names in it +$(TRACING_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TRACING_PKGS)) + $(prep-target) + $(call PackageFilter,$(TRACING_PKGS)) + +############################################################# +# +# Get a cache of all the directories +$(DIRECTORY_CACHE): $(ALL_SOURCE_DIRS) + $(prep-target) + @for cp in $(ALL_SOURCE_DIRS) ; do \ + $(ECHO) "$(FIND) $${cp} -type f >> $@"; \ + $(FIND) $${cp} -type f >> $@; \ + done + +############################################################# +#release version of core packages ######## +# Maximize performance and ensure that build number & milestone are set. + +rel-coredocs: sanitycheckcoredocs + $(MAKE) coredocs + +rel-docs: rel-coredocs $(ALL_OTHER_TARGETS) +# +# end of production targets + +otherdocs: $(ALL_OTHER_TARGETS) + +clean: + $(RM) -r $(DOCSDIR) $(DOCSTMPDIR) + +############################################################# # DEBUG TARGET # List the values defined in the makefile hierarchy, to make sure everything # is set properly, and to help identify values we can use instead of making new ones. @@ -714,9 +1211,14 @@ # * BUILD_NUMBER defaults to b00 if not set on command line with BUILD_NUMBER=<value> # * MILESTONE defaults to internal unless set to beta, rc, or fcs on command line # -.PHONY: echovalues + echovalues: @$(ECHO) "" + @$(ECHO) --------------Imports--------------------------- + @$(ECHO) "IMPORT_PACKAGES = $(IMPORT_PACKAGES)" + @$(ECHO) "IMPORT_PACKAGE_FILTER = $(IMPORT_PACKAGE_FILTER)" + @$(ECHO) --------------Imports--------------------------- + @$(ECHO) "" @$(ECHO) --------------Shared--------------------------- @$(ECHO) BUILD_NUMBER = $(BUILD_NUMBER) @$(ECHO) FULL_VERSION = $(FULL_VERSION) @@ -736,11 +1238,16 @@ @$(ECHO) --------------Shared--------------------------- @$(ECHO) "" @$(ECHO) --------------common/Defs--------------------------- - @$(ECHO) "RELEASEDOCS_SRCPATH" + @$(ECHO) "RELEASEDOCS_SOURCEPATH" @$(ECHO) " SHARE_SRC/classes: $(SHARE_SRC)/classes" @$(ECHO) " PLATFORM_SRC/classes: $(PLATFORM_SRC)/classes" @$(ECHO) " GENSRCDIR: $(GENSRCDIR)" + @$(ECHO) " SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub" @$(ECHO) " IMPORTSRCDIR: $(IMPORTSRCDIR)" - @$(ECHO) " SHARE_SRC/doc/stub: $(SHARE_SRC)/doc/stub" @$(ECHO) --------------common/Defs--------------------------- @$(ECHO) "" + +############################################################# +.PHONY: all docs coredocs rel-docs echovalues otherdocs rel-coredocs \ + sanitycheckcoredocs $(ALL_OTHER_TARGETS) +
--- a/make/java/java/FILES_java.gmk Thu Jul 15 20:11:45 2010 -0700 +++ b/make/java/java/FILES_java.gmk Tue Jul 20 22:21:31 2010 -0700 @@ -30,6 +30,7 @@ # JAVA_JAVA_java = \ java/lang/Object.java \ + java/lang/AutoCloseable.java \ java/lang/Class.java \ java/lang/Thread.java \ java/lang/Character.java \
--- a/make/java/security/Makefile Thu Jul 15 20:11:45 2010 -0700 +++ b/make/java/security/Makefile Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ # -# Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1996, 2010 Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -62,6 +62,11 @@ CACERTS_SRC = $(CACERTS_FILE) CACERTS_BUILD = $(LIBDIR)/security/cacerts +ifndef OPENJDK + BLACKLIST_SRC = $(CLOSED_SHARE_SRC)/lib/security/blacklist + BLACKLIST_BUILD = $(LIBDIR)/security/blacklist +endif + FILES_class = $(FILES_java:%.java=$(CLASSBINDIR)/%.class) # @@ -69,7 +74,11 @@ # include $(BUILDDIR)/common/Rules.gmk +ifdef OPENJDK build: properties policy cacerts +else +build: properties policy cacerts blacklist +endif install: all @@ -79,6 +88,8 @@ cacerts: classes $(CACERTS_BUILD) +blacklist: classes $(BLACKLIST_BUILD) + $(PROPS_BUILD): $(PROPS_SRC) $(install-file) @@ -88,9 +99,12 @@ $(CACERTS_BUILD): $(CACERTS_SRC) $(install-file) +$(BLACKLIST_BUILD): $(BLACKLIST_SRC) + $(install-file) + clean clobber:: .delete.classlist $(RM) -r $(CLASSBINDIR)/java/security - $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) + $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD) # Additional Rule for building sun.security.util $(CLASSBINDIR)/%.class: $(SHARE_SRC)/sun/%.java
--- a/make/mkdemo/Makefile Thu Jul 15 20:11:45 2010 -0700 +++ b/make/mkdemo/Makefile Tue Jul 20 22:21:31 2010 -0700 @@ -46,11 +46,11 @@ $(RM) -r $(DEMODIR)/nbproject $(MKDIR) -p $(DEMODIR) ( $(CD) $(SHARE_SRC)/demo && $(TAR) -cf - \ - `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ + `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ ( $(CD) $(DEMODIR) && $(TAR) -xf - ) ifndef OPENJDK ( $(CD) $(CLOSED_SHARE_SRC)/demo && $(TAR) -cf - \ - `find nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ + `$(FIND) nbproject $(SCM_DIRS_prune) -o -type f -print` ) | \ ( $(CD) $(DEMODIR) && $(TAR) -xf - ) endif
--- a/make/tools/src/build/tools/jarreorder/JarReorder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/make/tools/src/build/tools/jarreorder/JarReorder.java Tue Jul 20 22:21:31 2010 -0700 @@ -28,7 +28,6 @@ * combine with an argument list of files and directories, and * write a list of items to be included in a jar file. */ - package build.tools.jarreorder; import java.io.BufferedReader; @@ -36,74 +35,68 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.HashSet; -import java.util.Vector; import java.io.PrintStream; import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; public class JarReorder { // To deal with output - private static PrintStream out; + private PrintStream out; - private final static boolean useTopDir = false; - - private static void usage() { + private void usage() { String help; help = - "Usage: jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n" - + " order_list is a file containing names of files to load\n" - + " in order at the end of a jar file.\n" - + " exclude_list is a file containing names of files/directories\n" - + " NOT to be included in a jar file.\n"; - if (useTopDir) - help += - " top_dir is the top of the directory structure to be searched;\n" - + " the contents of the lists and remaining arguments are\n" - + " relative to this.\n"; - help += - "\n" - + "The order_list or exclude_list may be replaced by a \"_\" if no\n" - + "data is to be provided.\n" - + "\n" - + " The remaining arguments are files or directories to be included\n" - + " in a jar file, from which will be excluded thse entries which\n" - + " appear in the exclude list.\n"; + "Usage: jar JarReorder [-o <outputfile>] <order_list> <exclude_list> <file> ...\n" + + " order_list is a file containing names of files to load\n" + + " in order at the end of a jar file unless\n" + + " excluded in the exclude list.\n" + + " exclude_list is a file containing names of files/directories\n" + + " NOT to be included in a jar file.\n" + + "\n" + + "The order_list or exclude_list may be replaced by a \"-\" if no\n" + + "data is to be provided.\n" + + "\n" + + " The remaining arguments are files or directories to be included\n" + + " in a jar file, from which will be excluded those entries which\n" + + " appear in the exclude list.\n"; System.err.println(help); - System.exit(1); } /* - * Create a list of files to be included in a jar file, such that the - * some the files will appear in a specific order, and allowing certain + * Create the file list to be included in a jar file, such that the + * list will appear in a specific order, and allowing certain * files and directories to be excluded. * - * Command line arguments are + * Command path arguments are * - optional -o outputfile - * - name of a file containing a list of files to be included in a jar file. - * - name of a file containing a list of files (or directories) to be + * - name of a file containing a set of files to be included in a jar file. + * - name of a file containing a set of files (or directories) to be * excluded from the jar file. * - names of files or directories to be searched for files to include * in the jar file. */ public static void main(String[] args) { + JarReorder jr = new JarReorder(); + jr.run(args); + } - HashMap filesExcluded = new HashMap(); - Vector filesIncluded = new Vector(); - int fileArgs; - String topDirName = ""; + private void run(String args[]) { + int arglen = args.length; int argpos = 0; // Look for "-o outputfilename" option - if ( arglen > 0 ) { - if ( arglen >= 2 && args[0].equals("-o") ) { + if (arglen > 0) { + if (arglen >= 2 && args[0].equals("-o")) { try { out = new PrintStream(new FileOutputStream(args[1])); - } catch ( FileNotFoundException e ) { + } catch (FileNotFoundException e) { System.err.println("Error: " + e.getMessage()); e.printStackTrace(System.err); System.exit(1); @@ -118,128 +111,111 @@ out = System.out; } - fileArgs = useTopDir ? 3 : 2; - - if (arglen <= fileArgs) { + // Should be 2 or more args left + if (arglen <= 2) { usage(); + System.exit(1); } - // Read the ordered list of files to be included in rt.jar. - // Read the list of files/directories to be excluded from rt.jar. - - Vector orderList = readListFromFile(args[argpos], true); - Vector excludeList = readListFromFile(args[argpos+1], false); - if (useTopDir) { - topDirName = args[argpos+2]; - if (!topDirName.endsWith(File.separator)) - topDirName = topDirName + File.separator; - } + // Read the ordered set of files to be included in rt.jar. + // Read the set of files/directories to be excluded from rt.jar. + String classListFile = args[argpos]; + String excludeListFile = args[argpos + 1]; + argpos += 2; + arglen -= 2; - // Copy these lists into filesExcluded so that these files will be excluded - // from the file list. (The orderList files will be appended later.) + // Create 2 lists and a set of processed files + List<String> orderList = readListFromFile(classListFile, true); + List<String> excludeList = readListFromFile(excludeListFile, false); + Set<String> processed = new HashSet<String>(); - for (int i = 0; i < orderList.size(); ++i) { - String s = (String) orderList.elementAt(i); - filesExcluded.put(s, s); - } - for (int i = 0; i < excludeList.size(); ++i) { - String s = (String) excludeList.elementAt(i); - filesExcluded.put(s, s); - } + // Create set of all files and directories excluded, then expand + // that list completely + Set<String> excludeSet = new HashSet<String>(excludeList); + Set<String> allFilesExcluded = expand(null, excludeSet, processed); + + // Indicate all these have been processed, orderList too, kept to end. + processed.addAll(orderList); // The remaining arguments are names of files/directories to be included // in the jar file. - - String[] files = new String[arglen - fileArgs]; - for (int i = fileArgs; i < arglen; ++i) { - files[i-fileArgs] = args[argpos+i]; - filesExcluded.put(args[argpos+i], args[argpos+i]); + Set<String> inputSet = new HashSet<String>(); + for (int i = 0; i < arglen; ++i) { + String name = args[argpos + i]; + name = cleanPath(new File(name)); + if ( name != null && name.length() > 0 && !inputSet.contains(name) ) { + inputSet.add(name); + } } - // Expand file/directory list to file list excluding those - // read from the class list. + // Expand file/directory input so we get a complete set (except ordered) + // Should be everything not excluded and not in order list. + Set<String> allFilesIncluded = expand(null, inputSet, processed); - if (useTopDir) - expand(new File(topDirName), files, filesIncluded, filesExcluded, topDirName); - else - expand(null, files, filesIncluded, filesExcluded, null); + // Create simple sorted list so we can add ordered items at end. + List<String> allFiles = new ArrayList<String>(allFilesIncluded); + Collections.sort(allFiles); - // Now add the ordered list to the end of the expanded list. + // Now add the ordered set to the end of the list. // Add in REVERSE ORDER, so that the first element is closest to // the end (and the index). - - HashSet excludeSet = new HashSet(excludeList); for (int i = orderList.size() - 1; i >= 0; --i) { - String s = (String) orderList.elementAt(i); - if (excludeSet.contains(s)) { - System.err.println("Included file " + s + " is also excluded, skipping."); - continue; + String s = orderList.get(i); + if (allFilesExcluded.contains(s)) { + System.err.println("Included order file " + s + + " is also excluded, skipping."); + } else if (new File(s).exists()) { + allFiles.add(s); + } else { + System.err.println("Included order file " + s + + " missing, skipping."); } - if (new File(topDirName + s).exists()) - filesIncluded.addElement(s); - else - System.err.println("Included file "+s+" missing, skipping."); } - // Print results. - - for (int i = 0; i < filesIncluded.size(); ++i) { - if (useTopDir) { - out.print("-C "); - out.print(topDirName); - out.print(" "); - } - out.println((String)filesIncluded.elementAt(i)); + // Print final results. + for (String str : allFiles) { + out.println(str); } - out.flush(); out.close(); } - /* - * Read a file containing a list of files into a Vector. + * Read a file containing a list of files and directories into a List. */ - private static Vector readListFromFile(String fileName, - boolean addClassSuffix) { + private List<String> readListFromFile(String fileName, + boolean addClassSuffix) { BufferedReader br = null; - Vector v = new Vector(2000); - - if ("-".equals(fileName)) - return v; - + List<String> list = new ArrayList<String>(); + // If you see "-" for the name, just assume nothing was provided. + if ("-".equals(fileName)) { + return list; + } try { br = new BufferedReader(new FileReader(fileName)); - - // Read the input file a line at a time. # in column 1 is a comment. - + // Read the input file a path at a time. # in column 1 is a comment. while (true) { - String line = null; - line = br.readLine(); - - if (line == null) + String path = br.readLine(); + if (path == null) { break; - - if (line.length() == 0 || - line.charAt(0) == '#') + } + // Look for comments + path = path.trim(); + if (path.length() == 0 + || path.charAt(0) == '#') { continue; - - // Convert forward or back slashes to the type expected for - // the current platform. - - if (File.separatorChar == '/') - line = line.replace('\\', '/'); - else - line = line.replace('/', '\\'); - - line = line.trim(); - if (addClassSuffix) { - if (!line.endsWith(".class")) { - line = line + ".class"; - } + } + // Add trailing .class if necessary + if (addClassSuffix && !path.endsWith(".class")) { + path = path + ".class"; } - v.addElement(line); + // Normalize the path + path = cleanPath(new File(path)); + // Add to list + if (path != null && path.length() > 0 && !list.contains(path)) { + list.add(path); + } } br.close(); } catch (FileNotFoundException e) { @@ -249,68 +225,89 @@ e.printStackTrace(); System.exit(2); } - return v; + return list; } - /* - * Expands list of files to process into full list of all files that + * Expands inputSet (files or dirs) into full set of all files that * can be found by recursively descending directories. + * @param dir root directory + * @param inputSet set of files or dirs to look into + * @param processed files or dirs already processed + * @return set of files */ - private static void expand(File dir, String[] files, - Vector includedFiles, HashMap excludedFiles, - String topDirName) { - if (files == null) { - return; + private Set<String> expand(File dir, + Set<String> inputSet, + Set<String> processed) { + Set<String> includedFiles = new HashSet<String>(); + if (inputSet.isEmpty()) { + return includedFiles; } - for (int i = 0; i < files.length; i++) { - File f = (dir == null) ? new File(files[i]) - : new File(dir, files[i]); - if (f.isFile()) { - String filePath = f.getPath(); - - if (useTopDir) { - if (filePath.startsWith(topDirName)) - filePath = filePath.substring(topDirName.length()); + for (String name : inputSet) { + // Depending on start location + File f = (dir == null) ? new File(name) + : new File(dir, name); + // Normalized path to use + String path = cleanPath(f); + if (path != null && path.length() > 0 + && !processed.contains(path)) { + if (f.isFile()) { + // Not in the excludeList, add it to both lists + includedFiles.add(path); + processed.add(path); + } else if (f.isDirectory()) { + // Add the directory entries + String[] dirList = f.list(); + Set<String> dirInputSet = new HashSet<String>(); + for (String x : dirList) { + dirInputSet.add(x); + } + // Process all entries in this directory + Set<String> subList = expand(f, dirInputSet, processed); + includedFiles.addAll(subList); + processed.add(path); } - - if (filePath.length() >= 2 && - filePath.charAt(0) == '.' && - filePath.charAt(1) == File.separatorChar) - filePath = filePath.substring(2); - - if (!excludedFiles.containsKey(filePath)) { - excludedFiles.put(filePath, filePath); - includedFiles.addElement(filePath); - } - } else if (f.isDirectory()) { - String dirPath = f.getPath(); - dirPath = (dirPath.endsWith(File.separator)) ? dirPath : - (dirPath + File.separator); - - if (useTopDir) { - if (dirPath.startsWith(topDirName)) - dirPath = dirPath.substring(topDirName.length()); - } - - if (dirPath.length() >= 2 && - dirPath.charAt(0) == '.' && - dirPath.charAt(1) == File.separatorChar) - dirPath = dirPath.substring(2); - - if (!excludedFiles.containsKey(dirPath)) { - - // Sort the directory list so that entries in the jar file - // are in a repeatable order. The order itself is not particularly - // important. [File.list() is unpredictable.] - - String[] dirList = f.list(); - Arrays.sort(dirList); - expand(f, dirList, includedFiles, excludedFiles, topDirName); - } - } else { - System.err.println("Error accessing: " + f.getPath()); } } + return includedFiles; } + + private String cleanPath(File f) { + String path = f.getPath(); + if (f.isFile()) { + path = cleanFilePath(path); + } else if (f.isDirectory()) { + path = cleanDirPath(path); + } else { + System.err.println("WARNING: Path does not exist as file or directory: " + path); + path = null; + } + return path; + } + + private String cleanFilePath(String path) { + // Remove leading and trailing whitespace + path = path.trim(); + // Make all / and \ chars one + if (File.separatorChar == '/') { + path = path.replace('\\', '/'); + } else { + path = path.replace('/', '\\'); + } + // Remove leading ./ + if (path.startsWith("." + File.separator)) { + path = path.substring(2); + } + return path; + } + + private String cleanDirPath(String path) { + path = cleanFilePath(path); + // Make sure it ends with a file separator + if (!path.endsWith(File.separator)) { + path = path + File.separator; + } + return path; + } + }
--- a/src/share/bin/emessages.h Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/bin/emessages.h Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ #define JVM_ERROR1 "Error: Could not create the Java Virtual Machine.\n" GEN_ERROR #define JVM_ERROR2 "Error: Could not detach main thread.\n" JNI_ERROR -#define JVM_ERROR3 "Error: SPARC V8 processor detected; Server compiler requires V9 or better.\nUse Client compiler on V8 processors.\nCould not create the Java virtual machine." +#define JVM_ERROR3 "Error: SPARC V8 processor detected; Required V9 processors or better.\nUse JDK5 client compiler for V8 processors.\n" JVM_ERROR1 #define JAR_ERROR1 "Error: Failed to load Main-Class manifest attribute from\n%s\n%s" #define JAR_ERROR2 "Error: Unable to access jarfile %s" @@ -69,7 +69,8 @@ #define CFG_ERROR5 "Error: Could not determine application home." #define CFG_ERROR6 "Error: could not open `%s'" #define CFG_ERROR7 "Error: no known VMs. (check for corrupt jvm.cfg file)" -#define CFG_ERROR8 "Error: no `%s' JVM at `%s'." +#define CFG_ERROR8 "Error: missing `%s' JVM at `%s'.\nPlease install or use the JRE or JDK that contains these missing components." +#define CFG_ERROR9 "Error: could not determine JVM type." #define SPC_ERROR1 "Error: Syntax error in version specification \"%s\""
--- a/src/share/bin/java.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/bin/java.c Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -192,8 +192,8 @@ int ret; InvocationFunctions ifn; jlong start, end; - char jrepath[MAXPATHLEN], jvmpath[MAXPATHLEN]; - char ** original_argv = argv; + char jvmpath[MAXPATHLEN]; + char jrepath[MAXPATHLEN]; _fVersion = fullversion; _dVersion = dotversion; @@ -225,14 +225,17 @@ */ SelectVersion(argc, argv, &main_class); - /* copy original argv */ - JLI_TraceLauncher("Command line Args:\n"); - original_argv = (JLI_CopyArgs(argc, (const char**)argv)); + if (JLI_IsTraceLauncher()) { + int i; + printf("Command line args:\n"); + for (i = 0; i < argc ; i++) { + printf("argv[%d] = %s\n", i, argv[i]); + } + } CreateExecutionEnvironment(&argc, &argv, jrepath, sizeof(jrepath), - jvmpath, sizeof(jvmpath), - original_argv); + jvmpath, sizeof(jvmpath)); ifn.CreateJavaVM = 0; ifn.GetDefaultJavaVMInitArgs = 0; @@ -301,22 +304,43 @@ return ContinueInNewThread(&ifn, argc, argv, jarfile, classname, ret); } +/* + * Always detach the main thread so that it appears to have ended when + * the application's main method exits. This will invoke the + * uncaught exception handler machinery if main threw an + * exception. An uncaught exception handler cannot change the + * launcher's return code except by calling System.exit. + * + * Wait for all non-daemon threads to end, then destroy the VM. + * This will actually create a trivial new Java waiter thread + * named "DestroyJavaVM", but this will be seen as a different + * thread from the one that executed main, even though they are + * the same C thread. This allows mainThread.join() and + * mainThread.isAlive() to work as expected. + */ +#define LEAVE() \ + if ((*vm)->DetachCurrentThread(vm) != 0) { \ + JLI_ReportErrorMessage(JVM_ERROR2); \ + ret = 1; \ + } \ + (*vm)->DestroyJavaVM(vm); \ + return ret \ #define CHECK_EXCEPTION_NULL_LEAVE(e) \ if ((*env)->ExceptionOccurred(env)) { \ JLI_ReportExceptionDescription(env); \ - goto leave; \ + LEAVE(); \ } \ if ((e) == NULL) { \ JLI_ReportErrorMessage(JNI_ERROR); \ - goto leave; \ + LEAVE(); \ } #define CHECK_EXCEPTION_LEAVE(rv) \ if ((*env)->ExceptionOccurred(env)) { \ JLI_ReportExceptionDescription(env); \ ret = (rv); \ - goto leave; \ + LEAVE(); \ } int JNICALL @@ -349,8 +373,7 @@ PrintJavaVersion(env, showVersion); CHECK_EXCEPTION_LEAVE(0); if (printVersion) { - ret = 0; - goto leave; + LEAVE(); } } @@ -358,7 +381,7 @@ if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) { PrintUsage(env, printXUsage); CHECK_EXCEPTION_LEAVE(1); - goto leave; + LEAVE(); } FreeKnownVMs(); /* after last possible PrintUsage() */ @@ -430,30 +453,7 @@ * System.exit) will be non-zero if main threw an exception. */ ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1; - -leave: - /* - * Always detach the main thread so that it appears to have ended when - * the application's main method exits. This will invoke the - * uncaught exception handler machinery if main threw an - * exception. An uncaught exception handler cannot change the - * launcher's return code except by calling System.exit. - */ - if ((*vm)->DetachCurrentThread(vm) != 0) { - JLI_ReportErrorMessage(JVM_ERROR2); - ret = 1; - } - /* - * Wait for all non-daemon threads to end, then destroy the VM. - * This will actually create a trivial new Java waiter thread - * named "DestroyJavaVM", but this will be seen as a different - * thread from the one that executed main, even though they are - * the same C thread. This allows mainThread.join() and - * mainThread.isAlive() to work as expected. - */ - (*vm)->DestroyJavaVM(vm); - - return ret; + LEAVE(); } /* @@ -1076,15 +1076,17 @@ if (--argc >= 0) { if (jarflag) { *pjarfile = *argv++; - *pclassname = 0; + *pclassname = NULL; } else { - *pjarfile = 0; + *pjarfile = NULL; *pclassname = *argv++; } *pargc = argc; *pargv = argv; } - + if (*pjarfile == NULL && *pclassname == NULL) { + *pret = 1; + } return JNI_TRUE; }
--- a/src/share/bin/java.h Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/bin/java.h Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,13 +114,19 @@ #define GetArch() GetArchPath(CURRENT_DATA_MODEL) -void CreateExecutionEnvironment(int *_argc, - char ***_argv, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv); +/* + * Different platforms will implement this, here + * pargc is a pointer to the original argc, + * pargv is a pointer to the original argv, + * jrepath is an accessible path to the jre as determined by the call + * so_jrepath is the length of the buffer jrepath + * jvmpath is an accessible path to the jvm as determined by the call + * so_jvmpath is the length of the buffer jvmpath + */ +void CreateExecutionEnvironment(int *argc, char ***argv, + char *jrepath, jint so_jrepath, + char *jvmpath, jint so_jvmpath); + /* Reports an error message to stderr or a window as appropriate. */ void JLI_ReportErrorMessage(const char * message, ...);
--- a/src/share/bin/jli_util.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/bin/jli_util.c Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,23 +85,6 @@ } /* - * Makes a copy of arguments - */ -char** -JLI_CopyArgs(int argc, const char **iargv) -{ - int i; - char** oargv = (char**)JLI_MemAlloc(sizeof(char*)*(argc+1)); - for (i = 0 ; i < argc+1 ; i++) { - oargv[i] = (iargv[i] == NULL) ? NULL : JLI_StringDup(iargv[i]); - if (iargv[i] != NULL && JLI_IsTraceLauncher() == JNI_TRUE) { - printf("\targv[%d] = '%s'\n",i,iargv[i]); - } - } - return oargv; -} - -/* * debug helpers we use */ static jboolean _launcher_debug = JNI_FALSE;
--- a/src/share/bin/jli_util.h Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/bin/jli_util.h Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ void *JLI_MemRealloc(void *ptr, size_t size); char *JLI_StringDup(const char *s1); void JLI_MemFree(void *ptr); -char **JLI_CopyArgs(int argc, const char **iargv); int JLI_StrCCmp(const char *s1, const char* s2); @@ -56,10 +55,12 @@ #include <io.h> #define JLI_StrCaseCmp(p1, p2) stricmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strnicmp((p1), (p2), (p3)) +#define JLI_Snprintf _snprintf #else #include <unistd.h> #define JLI_StrCaseCmp(p1, p2) strcasecmp((p1), (p2)) #define JLI_StrNCaseCmp(p1, p2, p3) strncasecmp((p1), (p2), (p3)) +#define JLI_Snprintf snprintf #endif /* _WIN32 */ /*
--- a/src/share/classes/com/sun/beans/finder/InstanceFinder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/beans/finder/InstanceFinder.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ private final Class<? extends T> type; private final boolean allow; private final String suffix; - private String[] packages; + private volatile String[] packages; InstanceFinder(Class<? extends T> type, boolean allow, String suffix, String... packages) { this.type = type; @@ -49,9 +49,7 @@ } public String[] getPackages() { - return (this.packages.length > 0) - ? this.packages.clone() - : this.packages; + return this.packages.clone(); } public void setPackages(String... packages) {
--- a/src/share/classes/com/sun/beans/finder/MethodFinder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/beans/finder/MethodFinder.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,7 +118,7 @@ * @throws NoSuchMethodException if method is not accessible or is not found * in specified superclass or interface */ - private static Method findAccessibleMethod(Method method) throws NoSuchMethodException { + public static Method findAccessibleMethod(Method method) throws NoSuchMethodException { Class<?> type = method.getDeclaringClass(); if (Modifier.isPublic(type.getModifiers())) { return method;
--- a/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/beans/finder/PersistenceDelegateFinder.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,17 +47,22 @@ } public void register(Class<?> type, PersistenceDelegate delegate) { - if (delegate != null) { - this.registry.put(type, delegate); - } - else { - this.registry.remove(type); + synchronized (this.registry) { + if (delegate != null) { + this.registry.put(type, delegate); + } + else { + this.registry.remove(type); + } } } @Override public PersistenceDelegate find(Class<?> type) { - PersistenceDelegate delegate = this.registry.get(type); + PersistenceDelegate delegate; + synchronized (this.registry) { + delegate = this.registry.get(type); + } return (delegate != null) ? delegate : super.find(type); } }
--- a/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/beans/finder/PropertyEditorFinder.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,12 +64,18 @@ } public void register(Class<?> type, Class<?> editor) { - this.registry.put(type, editor); + synchronized (this.registry) { + this.registry.put(type, editor); + } } @Override public PropertyEditor find(Class<?> type) { - PropertyEditor editor = instantiate(this.registry.get(type), null); + Class<?> predefined; + synchronized (this.registry) { + predefined = this.registry.get(type); + } + PropertyEditor editor = instantiate(predefined, null); if (editor == null) { editor = super.find(type); if ((editor == null) && (null != type.getEnumConstants())) {
--- a/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java Tue Jul 20 22:21:31 2010 -0700 @@ -1440,10 +1440,6 @@ } } - public Insets getBorderInsets(Component c) { - return getBorderInsets(c, null); - } - public Insets getBorderInsets(Component c, Insets i) { SynthContext context = getContext(c);
--- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -271,7 +271,9 @@ } public void uninstallUI(JComponent c) { - getFileChooser().removeAll(); + c.removePropertyChangeListener(filterComboBoxModel); + approveButton.removeActionListener(getApproveSelectionAction()); + filenameTextField.removeActionListener(getApproveSelectionAction()); super.uninstallUI(c); } @@ -515,6 +517,7 @@ public void uninstallComponents(JFileChooser fc) { fc.removeAll(); + bottomPanel = null; if (filterComboBoxModel != null) { fc.removePropertyChangeListener(filterComboBoxModel); }
--- a/src/share/classes/java/awt/EventDispatchThread.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/awt/EventDispatchThread.java Tue Jul 20 22:21:31 2010 -0700 @@ -61,85 +61,43 @@ * @since 1.1 */ class EventDispatchThread extends Thread { + private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread"); private EventQueue theQueue; private boolean doDispatch = true; + private boolean threadDeathCaught = false; + private static final int ANY_EVENT = -1; private Vector<EventFilter> eventFilters = new Vector<EventFilter>(); - // used in handleException - private int modalFiltersCount = 0; EventDispatchThread(ThreadGroup group, String name, EventQueue queue) { super(group, name); - theQueue = queue; + setEventQueue(queue); } - void stopDispatchingImpl(boolean wait) { - // Note: We stop dispatching via a flag rather than using - // Thread.interrupt() because we can't guarantee that the wait() - // we interrupt will be EventQueue.getNextEvent()'s. -fredx 8-11-98 - - StopDispatchEvent stopEvent = new StopDispatchEvent(); - - // wait for the dispatcher to complete - if (Thread.currentThread() != this) { - - // fix 4122683, 4128923 - // Post an empty event to ensure getNextEvent is unblocked - // - // We have to use postEventPrivate instead of postEvent because - // EventQueue.pop calls EventDispatchThread.stopDispatching. - // Calling SunToolkit.flushPendingEvents in this case could - // lead to deadlock. - theQueue.postEventPrivate(stopEvent); - - if (wait) { - try { - join(); - } catch(InterruptedException e) { - } - } - } else { - stopEvent.dispatch(); - } - - theQueue.detachDispatchThread(this, false); - } - + /* + * Must be called on EDT only, that's why no synchronization + */ public void stopDispatching() { - stopDispatchingImpl(true); - } - - public void stopDispatchingLater() { - stopDispatchingImpl(false); - } - - class StopDispatchEvent extends AWTEvent implements ActiveEvent { - /* - * serialVersionUID - */ - static final long serialVersionUID = -3692158172100730735L; - - public StopDispatchEvent() { - super(EventDispatchThread.this,0); - } - - public void dispatch() { - doDispatch = false; - } + doDispatch = false; } public void run() { - try { - pumpEvents(new Conditional() { - public boolean evaluate() { - return true; + while (true) { + try { + pumpEvents(new Conditional() { + public boolean evaluate() { + return true; + } + }); + } finally { + EventQueue eq = getEventQueue(); + if (eq.detachDispatchThread(this) || threadDeathCaught) { + break; } - }); - } finally { - theQueue.detachDispatchThread(this, true); + } } } @@ -190,7 +148,6 @@ } } eventFilters.add(k, filter); - modalFiltersCount++; } else { eventFilters.add(filter); } @@ -200,28 +157,25 @@ void removeEventFilter(EventFilter filter) { synchronized (eventFilters) { - if (eventFilters.contains(filter)) { - if (filter instanceof ModalEventFilter) { - modalFiltersCount--; - } - eventFilters.remove(filter); - } + eventFilters.remove(filter); } } boolean pumpOneEventForFilters(int id) { + AWTEvent event = null; + boolean eventOK = false; try { - AWTEvent event; - boolean eventOK; - EventQueueDelegate.Delegate delegate = - EventQueueDelegate.getDelegate(); + EventQueue eq = null; + EventQueueDelegate.Delegate delegate = null; do { + // EventQueue may change during the dispatching + eq = getEventQueue(); + delegate = EventQueueDelegate.getDelegate(); + if (delegate != null && id == ANY_EVENT) { - event = delegate.getNextEvent(theQueue); + event = delegate.getNextEvent(eq); } else { - event = (id == ANY_EVENT) - ? theQueue.getNextEvent() - : theQueue.getNextEvent(id); + event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id); } eventOK = true; @@ -252,13 +206,15 @@ if (delegate != null) { handle = delegate.beforeDispatch(event); } - theQueue.dispatchEvent(event); + eq.dispatchEvent(event); if (delegate != null) { delegate.afterDispatch(event, handle); } + return true; } catch (ThreadDeath death) { + threadDeathCaught = true; return false; } @@ -267,12 +223,10 @@ // Threads in the AppContext } - // Can get and throw only unchecked exceptions - catch (RuntimeException e) { - processException(e); - } catch (Error e) { + catch (Throwable e) { processException(e); } + return true; } @@ -281,14 +235,14 @@ eventLog.fine("Processing exception: " + e); } getUncaughtExceptionHandler().uncaughtException(this, e); - // don't rethrow the exception to avoid EDT recreation } - boolean isDispatching(EventQueue eq) { - return theQueue.equals(eq); + public synchronized EventQueue getEventQueue() { + return theQueue; } - - EventQueue getEventQueue() { return theQueue; } + public synchronized void setEventQueue(EventQueue eq) { + theQueue = eq; + } private static class HierarchyEventFilter implements EventFilter { private Component modalComponent;
--- a/src/share/classes/java/awt/EventQueue.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/awt/EventQueue.java Tue Jul 20 22:21:31 2010 -0700 @@ -138,6 +138,15 @@ private final Lock pushPopLock; private final Condition pushPopCond; + /* + * Dummy runnable to wake up EDT from getNextEvent() after + push/pop is performed + */ + private final static Runnable dummyRunnable = new Runnable() { + public void run() { + } + }; + private EventDispatchThread dispatchThread; private final ThreadGroup threadGroup = @@ -219,22 +228,22 @@ * @param theEvent an instance of <code>java.awt.AWTEvent</code>, * or a subclass of it */ - final void postEventPrivate(AWTEvent theEvent) { + private final void postEventPrivate(AWTEvent theEvent) { theEvent.isPosted = true; pushPopLock.lock(); try { - if (dispatchThread == null && nextQueue == null) { + if (nextQueue != null) { + // Forward the event to the top of EventQueue stack + nextQueue.postEventPrivate(theEvent); + return; + } + if (dispatchThread == null) { if (theEvent.getSource() == AWTAutoShutdown.getInstance()) { return; } else { initDispatchThread(); } } - if (nextQueue != null) { - // Forward event to top of EventQueue stack. - nextQueue.postEventPrivate(theEvent); - return; - } postEvent(theEvent, getPriority(theEvent)); } finally { pushPopLock.unlock(); @@ -242,29 +251,20 @@ } private static int getPriority(AWTEvent theEvent) { - if (theEvent instanceof PeerEvent && - (((PeerEvent)theEvent).getFlags() & - PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) - { - return ULTIMATE_PRIORITY; + if (theEvent instanceof PeerEvent) { + PeerEvent peerEvent = (PeerEvent)theEvent; + if ((peerEvent.getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) { + return ULTIMATE_PRIORITY; + } + if ((peerEvent.getFlags() & PeerEvent.PRIORITY_EVENT) != 0) { + return HIGH_PRIORITY; + } + if ((peerEvent.getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) { + return LOW_PRIORITY; + } } - - if (theEvent instanceof PeerEvent && - (((PeerEvent)theEvent).getFlags() & - PeerEvent.PRIORITY_EVENT) != 0) - { - return HIGH_PRIORITY; - } - - if (theEvent instanceof PeerEvent && - (((PeerEvent)theEvent).getFlags() & - PeerEvent.LOW_PRIORITY_EVENT) != 0) - { - return LOW_PRIORITY; - } - int id = theEvent.getID(); - if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) { + if ((id >= PaintEvent.PAINT_FIRST) && (id <= PaintEvent.PAINT_LAST)) { return LOW_PRIORITY; } return NORM_PRIORITY; @@ -501,16 +501,9 @@ SunToolkit.flushPendingEvents(); pushPopLock.lock(); try { - for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { - if (queues[i].head != null) { - EventQueueItem entry = queues[i].head; - queues[i].head = entry.next; - if (entry.next == null) { - queues[i].tail = null; - } - uncacheEQItem(entry); - return entry.event; - } + AWTEvent event = getNextEventPrivate(); + if (event != null) { + return event; } AWTAutoShutdown.getInstance().notifyThreadFree(dispatchThread); pushPopCond.await(); @@ -520,6 +513,24 @@ } while(true); } + /* + * Must be called under the lock. Doesn't call flushPendingEvents() + */ + AWTEvent getNextEventPrivate() throws InterruptedException { + for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { + if (queues[i].head != null) { + EventQueueItem entry = queues[i].head; + queues[i].head = entry.next; + if (entry.next == null) { + queues[i].tail = null; + } + uncacheEQItem(entry); + return entry.event; + } + } + return null; + } + AWTEvent getNextEvent(int id) throws InterruptedException { do { /* @@ -659,7 +670,9 @@ dispatchThread.stopDispatching(); } } else { - System.err.println("unable to dispatch event: " + event); + if (eventLog.isLoggable(PlatformLogger.FINE)) { + eventLog.fine("Unable to dispatch event: " + event); + } } } @@ -761,15 +774,23 @@ pushPopLock.lock(); try { - EventQueue toPush = this; - while (toPush.nextQueue != null) { - toPush = toPush.nextQueue; + EventQueue topQueue = this; + while (topQueue.nextQueue != null) { + topQueue = topQueue.nextQueue; + } + + if ((topQueue.dispatchThread != null) && + (topQueue.dispatchThread.getEventQueue() == this)) + { + newEventQueue.dispatchThread = topQueue.dispatchThread; + topQueue.dispatchThread.setEventQueue(newEventQueue); } // Transfer all events forward to new EventQueue. - while (toPush.peekEvent() != null) { + while (topQueue.peekEvent() != null) { try { - newEventQueue.postEventPrivate(toPush.getNextEvent()); + // Use getNextEventPrivate() as it doesn't call flushPendingEvents() + newEventQueue.postEventPrivate(topQueue.getNextEventPrivate()); } catch (InterruptedException ie) { if (eventLog.isLoggable(PlatformLogger.FINE)) { eventLog.fine("Interrupted push", ie); @@ -777,28 +798,21 @@ } } - newEventQueue.previousQueue = toPush; + // Wake up EDT waiting in getNextEvent(), so it can + // pick up a new EventQueue. Post the waking event before + // topQueue.nextQueue is assigned, otherwise the event would + // go newEventQueue + topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable)); - /* - * Stop the event dispatch thread associated with the currently - * active event queue, so that after the new queue is pushed - * on the top this event dispatch thread won't prevent AWT from - * being automatically shut down. - * Use stopDispatchingLater() to avoid deadlock: stopDispatching() - * waits for the dispatch thread to exit, which in turn waits - * for the lock in EQ.detachDispatchThread(), which is hold by - * this method. - */ - if (toPush.dispatchThread != null) { - toPush.dispatchThread.stopDispatchingLater(); + newEventQueue.previousQueue = topQueue; + topQueue.nextQueue = newEventQueue; + + AppContext appContext = AppContext.getAppContext(); + if (appContext.get(AppContext.EVENT_QUEUE_KEY) == topQueue) { + appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue); } - toPush.nextQueue = newEventQueue; - - AppContext appContext = AppContext.getAppContext(); - if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) { - appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue); - } + pushPopCond.signalAll(); } finally { pushPopLock.unlock(); } @@ -822,44 +836,51 @@ eventLog.fine("EventQueue.pop(" + this + ")"); } - EventDispatchThread dt = null; pushPopLock.lock(); try { - EventQueue toPop = this; - while (toPop.nextQueue != null) { - toPop = toPop.nextQueue; + EventQueue topQueue = this; + while (topQueue.nextQueue != null) { + topQueue = topQueue.nextQueue; } - EventQueue prev = toPop.previousQueue; - if (prev == null) { + EventQueue prevQueue = topQueue.previousQueue; + if (prevQueue == null) { throw new EmptyStackException(); } - toPop.previousQueue = null; + + topQueue.previousQueue = null; + prevQueue.nextQueue = null; // Transfer all events back to previous EventQueue. - prev.nextQueue = null; - while (toPop.peekEvent() != null) { + while (topQueue.peekEvent() != null) { try { - prev.postEventPrivate(toPop.getNextEvent()); + prevQueue.postEventPrivate(topQueue.getNextEventPrivate()); } catch (InterruptedException ie) { if (eventLog.isLoggable(PlatformLogger.FINE)) { eventLog.fine("Interrupted pop", ie); } } } - AppContext appContext = AppContext.getAppContext(); - if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) { - appContext.put(AppContext.EVENT_QUEUE_KEY, prev); + + if ((topQueue.dispatchThread != null) && + (topQueue.dispatchThread.getEventQueue() == this)) + { + prevQueue.dispatchThread = topQueue.dispatchThread; + topQueue.dispatchThread.setEventQueue(prevQueue); } - dt = toPop.dispatchThread; + AppContext appContext = AppContext.getAppContext(); + if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) { + appContext.put(AppContext.EVENT_QUEUE_KEY, prevQueue); + } + + // Wake up EDT waiting in getNextEvent(), so it can + // pick up a new EventQueue + topQueue.postEventPrivate(new InvocationEvent(topQueue, dummyRunnable)); + + pushPopCond.signalAll(); } finally { pushPopLock.unlock(); } - - if (dt != null) { - dt.stopDispatching(); // Must be done outside synchronized - // block to avoid possible deadlock - } } /** @@ -907,9 +928,9 @@ try { AppContext appContext = AppContext.getAppContext(); if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) { - dispatchThread = (EventDispatchThread) - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + dispatchThread = AccessController.doPrivileged( + new PrivilegedAction<EventDispatchThread>() { + public EventDispatchThread run() { EventDispatchThread t = new EventDispatchThread(threadGroup, name, @@ -919,7 +940,8 @@ t.setDaemon(false); return t; } - }); + } + ); AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); dispatchThread.start(); } @@ -928,7 +950,7 @@ } } - final void detachDispatchThread(EventDispatchThread edt, boolean restart) { + final boolean detachDispatchThread(EventDispatchThread edt) { /* * This synchronized block is to secure that the event dispatch * thread won't die in the middle of posting a new event to the @@ -939,26 +961,21 @@ */ pushPopLock.lock(); try { - EventDispatchThread oldDispatchThread = dispatchThread; - if (dispatchThread == edt) { - dispatchThread = null; - } - if (restart) { + if (edt == dispatchThread) { /* - * Event dispatch thread dies in case of an uncaught exception. - * A new event dispatch thread for this queue will be started - * only if a new event is posted to it. In case if no more - * events are posted after this thread died all events that - * currently are in the queue will never be dispatched. + * Don't detach the thread if any events are pending. Not + * sure if it's a possible scenario, though. * * Fix for 4648733. Check both the associated java event * queue and the PostEventQueue. */ if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) { - initDispatchThread(); + return false; } - AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread); + dispatchThread = null; } + AWTAutoShutdown.getInstance().notifyThreadFree(edt); + return true; } finally { pushPopLock.unlock(); }
--- a/src/share/classes/java/beans/Encoder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/Encoder.java Tue Jul 20 22:21:31 2010 -0700 @@ -194,13 +194,8 @@ * @see java.beans.BeanInfo#getBeanDescriptor */ public PersistenceDelegate getPersistenceDelegate(Class<?> type) { - synchronized (this.finder) { - PersistenceDelegate pd = this.finder.find(type); - if (pd != null) { - return pd; - } - } - return MetaData.getPersistenceDelegate(type); + PersistenceDelegate pd = this.finder.find(type); + return (pd != null) ? pd : MetaData.getPersistenceDelegate(type); } /** @@ -214,9 +209,7 @@ * @see java.beans.BeanInfo#getBeanDescriptor */ public void setPersistenceDelegate(Class<?> type, PersistenceDelegate delegate) { - synchronized (this.finder) { - this.finder.register(type, delegate); - } + this.finder.register(type, delegate); } /**
--- a/src/share/classes/java/beans/EventSetDescriptor.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/EventSetDescriptor.java Tue Jul 20 22:21:31 2010 -0700 @@ -27,6 +27,7 @@ import java.lang.ref.Reference; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; /** * An EventSetDescriptor describes a group of events that a given Java @@ -175,10 +176,8 @@ setRemoveListenerMethod(getMethod(sourceClass, removeListenerMethodName, 1)); // Be more forgiving of not finding the getListener method. - Method method = Introspector.findMethod(sourceClass, - getListenerMethodName, 0); - if (method != null) { - setGetListenerMethod(method); + if (getListenerMethodName != null) { + setGetListenerMethod(Introspector.findInstanceMethod(sourceClass, getListenerMethodName)); } } @@ -188,7 +187,7 @@ return null; } Method method = Introspector.findMethod(cls, name, args); - if (method == null) { + if ((method == null) || Modifier.isStatic(method.getModifiers())) { throw new IntrospectionException("Method not found: " + name + " on class " + cls.getName()); }
--- a/src/share/classes/java/beans/IndexedPropertyDescriptor.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/IndexedPropertyDescriptor.java Tue Jul 20 22:21:31 2010 -0700 @@ -189,16 +189,11 @@ indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); } } - - Class[] args = { int.class }; - - indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, - 1, args); + indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); if (indexedReadMethod == null) { // no "is" method, so look for a "get" method. indexedReadMethodName = Introspector.GET_PREFIX + getBaseName(); - indexedReadMethod = Introspector.findMethod(cls, indexedReadMethodName, - 1, args); + indexedReadMethod = Introspector.findInstanceMethod(cls, indexedReadMethodName, int.class); } setIndexedReadMethod0(indexedReadMethod); } @@ -270,8 +265,7 @@ if (indexedWriteMethodName == null) { indexedWriteMethodName = Introspector.SET_PREFIX + getBaseName(); } - indexedWriteMethod = Introspector.findMethod(cls, indexedWriteMethodName, - 2, (type == null) ? null : new Class[] { int.class, type }); + indexedWriteMethod = Introspector.findInstanceMethod(cls, indexedWriteMethodName, int.class, type); if (indexedWriteMethod != null) { if (!indexedWriteMethod.getReturnType().equals(void.class)) { indexedWriteMethod = null;
--- a/src/share/classes/java/beans/Introspector.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/Introspector.java Tue Jul 20 22:21:31 2010 -0700 @@ -28,6 +28,7 @@ import com.sun.beans.WeakCache; import com.sun.beans.finder.BeanInfoFinder; import com.sun.beans.finder.ClassFinder; +import com.sun.beans.finder.MethodFinder; import java.lang.ref.Reference; import java.lang.ref.SoftReference; @@ -157,21 +158,23 @@ if (!ReflectUtil.isPackageAccessible(beanClass)) { return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); } + Map<Class<?>, BeanInfo> beanInfoCache; + BeanInfo beanInfo; synchronized (BEANINFO_CACHE) { - Map<Class<?>, BeanInfo> beanInfoCache = - (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); - + beanInfoCache = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); if (beanInfoCache == null) { beanInfoCache = new WeakHashMap<Class<?>, BeanInfo>(); AppContext.getAppContext().put(BEANINFO_CACHE, beanInfoCache); } - BeanInfo beanInfo = beanInfoCache.get(beanClass); - if (beanInfo == null) { - beanInfo = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); + beanInfo = beanInfoCache.get(beanClass); + } + if (beanInfo == null) { + beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo(); + synchronized (BEANINFO_CACHE) { beanInfoCache.put(beanClass, beanInfo); } - return beanInfo; } + return beanInfo; } /** @@ -301,10 +304,7 @@ */ public static String[] getBeanInfoSearchPath() { - BeanInfoFinder finder = getFinder(); - synchronized (finder) { - return finder.getPackages(); - } + return getFinder().getPackages(); } /** @@ -328,10 +328,7 @@ if (sm != null) { sm.checkPropertiesAccess(); } - BeanInfoFinder finder = getFinder(); - synchronized (finder) { - finder.setPackages(path); - } + getFinder().setPackages(path); } @@ -453,10 +450,7 @@ * @return Instance of an explicit BeanInfo class or null if one isn't found. */ private static BeanInfo findExplicitBeanInfo(Class beanClass) { - BeanInfoFinder finder = getFinder(); - synchronized (finder) { - return finder.find(beanClass); - } + return getFinder().find(beanClass); } /** @@ -849,8 +843,8 @@ Method read = result.getReadMethod(); if (read == null && write != null) { - read = findMethod(result.getClass0(), - GET_PREFIX + NameGenerator.capitalize(result.getName()), 0); + read = findInstanceMethod(result.getClass0(), + GET_PREFIX + NameGenerator.capitalize(result.getName())); if (read != null) { try { result.setReadMethod(read); @@ -860,9 +854,9 @@ } } if (write == null && read != null) { - write = findMethod(result.getClass0(), - SET_PREFIX + NameGenerator.capitalize(result.getName()), 1, - new Class[] { FeatureDescriptor.getReturnType(result.getClass0(), read) }); + write = findInstanceMethod(result.getClass0(), + SET_PREFIX + NameGenerator.capitalize(result.getName()), + FeatureDescriptor.getReturnType(result.getClass0(), read)); if (write != null) { try { result.setWriteMethod(write); @@ -1286,90 +1280,27 @@ // Package private support methods. //====================================================================== - /** - * Internal support for finding a target methodName with a given - * parameter list on a given class. - */ - private static Method internalFindMethod(Class start, String methodName, - int argCount, Class args[]) { - // For overriden methods we need to find the most derived version. - // So we start with the given class and walk up the superclass chain. - - Method method = null; - - for (Class cl = start; cl != null; cl = cl.getSuperclass()) { - Method methods[] = getPublicDeclaredMethods(cl); - for (int i = 0; i < methods.length; i++) { - method = methods[i]; - if (method == null) { - continue; + static Method findMethod(Class<?> type, String name, int args) { + for (Method method : type.getMethods()) { + if (method.getName().equals(name) && (args == method.getParameterTypes().length)) { + try { + return MethodFinder.findAccessibleMethod(method); } - - // make sure method signature matches. - Class params[] = FeatureDescriptor.getParameterTypes(start, method); - if (method.getName().equals(methodName) && - params.length == argCount) { - if (args != null) { - boolean different = false; - if (argCount > 0) { - for (int j = 0; j < argCount; j++) { - if (params[j] != args[j]) { - different = true; - continue; - } - } - if (different) { - continue; - } - } - } - return method; + catch (NoSuchMethodException exception) { + // continue search for a method with the specified count of parameters } } } - method = null; - - // Now check any inherited interfaces. This is necessary both when - // the argument class is itself an interface, and when the argument - // class is an abstract class. - Class ifcs[] = start.getInterfaces(); - for (int i = 0 ; i < ifcs.length; i++) { - // Note: The original implementation had both methods calling - // the 3 arg method. This is preserved but perhaps it should - // pass the args array instead of null. - method = internalFindMethod(ifcs[i], methodName, argCount, null); - if (method != null) { - break; - } - } - return method; + return null; } - /** - * Find a target methodName on a given class. - */ - static Method findMethod(Class cls, String methodName, int argCount) { - return findMethod(cls, methodName, argCount, null); - } - - /** - * Find a target methodName with specific parameter list on a given class. - * <p> - * Used in the contructors of the EventSetDescriptor, - * PropertyDescriptor and the IndexedPropertyDescriptor. - * <p> - * @param cls The Class object on which to retrieve the method. - * @param methodName Name of the method. - * @param argCount Number of arguments for the desired method. - * @param args Array of argument types for the method. - * @return the method or null if not found - */ - static Method findMethod(Class cls, String methodName, int argCount, - Class args[]) { - if (methodName == null) { + static Method findInstanceMethod(Class<?> type, String name, Class<?>... args) { + try { + return MethodFinder.findInstanceMethod(type, name, args); + } + catch (NoSuchMethodException exception) { return null; } - return internalFindMethod(cls, methodName, argCount, args); } /**
--- a/src/share/classes/java/beans/MethodDescriptor.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/MethodDescriptor.java Tue Jul 20 22:21:31 2010 -0700 @@ -82,21 +82,21 @@ Method method = getMethod0(); if (method == null) { Class cls = getClass0(); - if (cls != null) { + String name = getName(); + if ((cls != null) && (name != null)) { Class[] params = getParams(); if (params == null) { for (int i = 0; i < 3; i++) { // Find methods for up to 2 params. We are guessing here. // This block should never execute unless the classloader // that loaded the argument classes disappears. - method = Introspector.findMethod(cls, getName(), i, null); + method = Introspector.findMethod(cls, name, i); if (method != null) { break; } } } else { - method = Introspector.findMethod(cls, getName(), - params.length, params); + method = Statement.getMethod(cls, name, params); } setMethod(method); }
--- a/src/share/classes/java/beans/PropertyDescriptor.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/PropertyDescriptor.java Tue Jul 20 22:21:31 2010 -0700 @@ -112,9 +112,7 @@ // If this class or one of its base classes allow PropertyChangeListener, // then we assume that any properties we discover are "bound". // See Introspector.getTargetPropertyInfo() method. - String name = "addPropertyChangeListener"; - Class[] args = {PropertyChangeListener.class}; - this.bound = (null != Introspector.findMethod(beanClass, name, args.length, args)); + this.bound = null != Introspector.findInstanceMethod(beanClass, "addPropertyChangeListener", PropertyChangeListener.class); } /** @@ -225,10 +223,10 @@ // property type is. For booleans, there can be "is" and "get" // methods. If an "is" method exists, this is the official // reader method so look for this one first. - readMethod = Introspector.findMethod(cls, readMethodName, 0); + readMethod = Introspector.findInstanceMethod(cls, readMethodName); if (readMethod == null) { readMethodName = Introspector.GET_PREFIX + getBaseName(); - readMethod = Introspector.findMethod(cls, readMethodName, 0); + readMethod = Introspector.findInstanceMethod(cls, readMethodName); } try { setReadMethod(readMethod); @@ -293,8 +291,7 @@ writeMethodName = Introspector.SET_PREFIX + getBaseName(); } - writeMethod = Introspector.findMethod(cls, writeMethodName, 1, - (type == null) ? null : new Class[] { type }); + writeMethod = Introspector.findInstanceMethod(cls, writeMethodName, type); if (writeMethod != null) { if (!writeMethod.getReturnType().equals(void.class)) { writeMethod = null;
--- a/src/share/classes/java/beans/PropertyEditorManager.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/PropertyEditorManager.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,10 +81,7 @@ if (sm != null) { sm.checkPropertiesAccess(); } - PropertyEditorFinder finder = getFinder(); - synchronized (finder) { - finder.register(targetType, editorClass); - } + getFinder().register(targetType, editorClass); } /** @@ -95,10 +92,7 @@ * The result is null if no suitable editor can be found. */ public static PropertyEditor findEditor(Class<?> targetType) { - PropertyEditorFinder finder = getFinder(); - synchronized (finder) { - return finder.find(targetType); - } + return getFinder().find(targetType); } /** @@ -110,10 +104,7 @@ * e.g. Sun implementation initially sets to {"sun.beans.editors"}. */ public static String[] getEditorSearchPath() { - PropertyEditorFinder finder = getFinder(); - synchronized (finder) { - return finder.getPackages(); - } + return getFinder().getPackages(); } /** @@ -134,10 +125,7 @@ if (sm != null) { sm.checkPropertiesAccess(); } - PropertyEditorFinder finder = getFinder(); - synchronized (finder) { - finder.setPackages(path); - } + getFinder().setPackages(path); } private static PropertyEditorFinder getFinder() {
--- a/src/share/classes/java/beans/XMLDecoder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/XMLDecoder.java Tue Jul 20 22:21:31 2010 -0700 @@ -60,7 +60,7 @@ * * @author Philip Milne */ -public class XMLDecoder { +public class XMLDecoder implements AutoCloseable { private final DocumentHandler handler = new DocumentHandler(); private final InputSource input; private Object owner;
--- a/src/share/classes/java/beans/XMLEncoder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/beans/XMLEncoder.java Tue Jul 20 22:21:31 2010 -0700 @@ -204,7 +204,7 @@ * * @author Philip Milne */ -public class XMLEncoder extends Encoder { +public class XMLEncoder extends Encoder implements AutoCloseable { private final CharsetEncoder encoder; private final String charset;
--- a/src/share/classes/java/io/Bits.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/io/Bits.java Tue Jul 20 22:21:31 2010 -0700 @@ -41,51 +41,39 @@ } static char getChar(byte[] b, int off) { - return (char) (((b[off + 1] & 0xFF) << 0) + - ((b[off + 0]) << 8)); + return (char) ((b[off + 1] & 0xFF) + + (b[off] << 8)); } static short getShort(byte[] b, int off) { - return (short) (((b[off + 1] & 0xFF) << 0) + - ((b[off + 0]) << 8)); + return (short) ((b[off + 1] & 0xFF) + + (b[off] << 8)); } static int getInt(byte[] b, int off) { - return ((b[off + 3] & 0xFF) << 0) + - ((b[off + 2] & 0xFF) << 8) + + return ((b[off + 3] & 0xFF) ) + + ((b[off + 2] & 0xFF) << 8) + ((b[off + 1] & 0xFF) << 16) + - ((b[off + 0]) << 24); + ((b[off ] ) << 24); } static float getFloat(byte[] b, int off) { - int i = ((b[off + 3] & 0xFF) << 0) + - ((b[off + 2] & 0xFF) << 8) + - ((b[off + 1] & 0xFF) << 16) + - ((b[off + 0]) << 24); - return Float.intBitsToFloat(i); + return Float.intBitsToFloat(getInt(b, off)); } static long getLong(byte[] b, int off) { - return ((b[off + 7] & 0xFFL) << 0) + - ((b[off + 6] & 0xFFL) << 8) + + return ((b[off + 7] & 0xFFL) ) + + ((b[off + 6] & 0xFFL) << 8) + ((b[off + 5] & 0xFFL) << 16) + ((b[off + 4] & 0xFFL) << 24) + ((b[off + 3] & 0xFFL) << 32) + ((b[off + 2] & 0xFFL) << 40) + ((b[off + 1] & 0xFFL) << 48) + - (((long) b[off + 0]) << 56); + (((long) b[off]) << 56); } static double getDouble(byte[] b, int off) { - long j = ((b[off + 7] & 0xFFL) << 0) + - ((b[off + 6] & 0xFFL) << 8) + - ((b[off + 5] & 0xFFL) << 16) + - ((b[off + 4] & 0xFFL) << 24) + - ((b[off + 3] & 0xFFL) << 32) + - ((b[off + 2] & 0xFFL) << 40) + - ((b[off + 1] & 0xFFL) << 48) + - (((long) b[off + 0]) << 56); - return Double.longBitsToDouble(j); + return Double.longBitsToDouble(getLong(b, off)); } /* @@ -98,50 +86,38 @@ } static void putChar(byte[] b, int off, char val) { - b[off + 1] = (byte) (val >>> 0); - b[off + 0] = (byte) (val >>> 8); + b[off + 1] = (byte) (val ); + b[off ] = (byte) (val >>> 8); } static void putShort(byte[] b, int off, short val) { - b[off + 1] = (byte) (val >>> 0); - b[off + 0] = (byte) (val >>> 8); + b[off + 1] = (byte) (val ); + b[off ] = (byte) (val >>> 8); } static void putInt(byte[] b, int off, int val) { - b[off + 3] = (byte) (val >>> 0); - b[off + 2] = (byte) (val >>> 8); + b[off + 3] = (byte) (val ); + b[off + 2] = (byte) (val >>> 8); b[off + 1] = (byte) (val >>> 16); - b[off + 0] = (byte) (val >>> 24); + b[off ] = (byte) (val >>> 24); } static void putFloat(byte[] b, int off, float val) { - int i = Float.floatToIntBits(val); - b[off + 3] = (byte) (i >>> 0); - b[off + 2] = (byte) (i >>> 8); - b[off + 1] = (byte) (i >>> 16); - b[off + 0] = (byte) (i >>> 24); + putInt(b, off, Float.floatToIntBits(val)); } static void putLong(byte[] b, int off, long val) { - b[off + 7] = (byte) (val >>> 0); - b[off + 6] = (byte) (val >>> 8); + b[off + 7] = (byte) (val ); + b[off + 6] = (byte) (val >>> 8); b[off + 5] = (byte) (val >>> 16); b[off + 4] = (byte) (val >>> 24); b[off + 3] = (byte) (val >>> 32); b[off + 2] = (byte) (val >>> 40); b[off + 1] = (byte) (val >>> 48); - b[off + 0] = (byte) (val >>> 56); + b[off ] = (byte) (val >>> 56); } static void putDouble(byte[] b, int off, double val) { - long j = Double.doubleToLongBits(val); - b[off + 7] = (byte) (j >>> 0); - b[off + 6] = (byte) (j >>> 8); - b[off + 5] = (byte) (j >>> 16); - b[off + 4] = (byte) (j >>> 24); - b[off + 3] = (byte) (j >>> 32); - b[off + 2] = (byte) (j >>> 40); - b[off + 1] = (byte) (j >>> 48); - b[off + 0] = (byte) (j >>> 56); + putLong(b, off, Double.doubleToLongBits(val)); } }
--- a/src/share/classes/java/io/Closeable.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/io/Closeable.java Tue Jul 20 22:21:31 2010 -0700 @@ -28,14 +28,14 @@ import java.io.IOException; /** - * A <tt>Closeable</tt> is a source or destination of data that can be closed. + * A {@code Closeable} is a source or destination of data that can be closed. * The close method is invoked to release resources that the object is * holding (such as open files). * * @since 1.5 */ -public interface Closeable { +public interface Closeable extends AutoCloseable { /** * Closes this stream and releases any system resources associated @@ -45,5 +45,4 @@ * @throws IOException if an I/O error occurs */ public void close() throws IOException; - }
--- a/src/share/classes/java/io/ObjectInput.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/io/ObjectInput.java Tue Jul 20 22:21:31 2010 -0700 @@ -36,7 +36,7 @@ * @see java.io.ObjectInputStream * @since JDK1.1 */ -public interface ObjectInput extends DataInput { +public interface ObjectInput extends DataInput, AutoCloseable { /** * Read and return an object. The class that implements this interface * defines where the object is "read" from.
--- a/src/share/classes/java/io/ObjectOutput.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/io/ObjectOutput.java Tue Jul 20 22:21:31 2010 -0700 @@ -36,7 +36,7 @@ * @see java.io.ObjectInputStream * @since JDK1.1 */ -public interface ObjectOutput extends DataOutput { +public interface ObjectOutput extends DataOutput, AutoCloseable { /** * Write an object to the underlying storage or stream. The * class that implements this interface defines how the object is
--- a/src/share/classes/java/lang/AbstractStringBuilder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/lang/AbstractStringBuilder.java Tue Jul 20 22:21:31 2010 -0700 @@ -721,20 +721,19 @@ * {@code codePoint} isn't a valid Unicode code point */ public AbstractStringBuilder appendCodePoint(int codePoint) { - if (!Character.isValidCodePoint(codePoint)) { + final int count = this.count; + + if (Character.isBmpCodePoint(codePoint)) { + ensureCapacityInternal(count + 1); + value[count] = (char) codePoint; + this.count = count + 1; + } else if (Character.isValidCodePoint(codePoint)) { + ensureCapacityInternal(count + 2); + Character.toSurrogates(codePoint, value, count); + this.count = count + 2; + } else { throw new IllegalArgumentException(); } - int n = 1; - if (codePoint >= Character.MIN_SUPPLEMENTARY_CODE_POINT) { - n++; - } - ensureCapacityInternal(count + n); - if (n == 1) { - value[count++] = (char) codePoint; - } else { - Character.toSurrogates(codePoint, value, count); - count += n; - } return this; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/java/lang/AutoCloseable.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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; + +/** + * A resource that must be closed when it is no longer needed. + * + * @author Josh Bloch + * @since 1.7 + */ +public interface AutoCloseable { + /** + * Close this resource, relinquishing any underlying resources. + * This method is invoked automatically by the automatic resource + * management block construct. + * + * <p>Classes implementing this method are strongly encouraged to + * be declared to throw more specific exceptions (or no exception + * at all, if the close cannot fail). + * + * @throws Exception if this resource cannot be closed + */ + void close() throws Exception; +}
--- a/src/share/classes/java/lang/Character.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/lang/Character.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ */ package java.lang; + import java.util.Arrays; import java.util.Map; import java.util.HashMap; @@ -67,17 +68,16 @@ * definition</i></a> of the U+<i>n</i> notation in the Unicode * standard.) * - * <p>The set of characters from U+0000 to U+FFFF is sometimes - * referred to as the <em>Basic Multilingual Plane (BMP)</em>. <a - * name="supplementary">Characters</a> whose code points are greater + * <p><a name="BMP">The set of characters from U+0000 to U+FFFF is + * sometimes referred to as the <em>Basic Multilingual Plane (BMP)</em>. + * <a name="supplementary">Characters</a> whose code points are greater * than U+FFFF are called <em>supplementary character</em>s. The Java - * 2 platform uses the UTF-16 representation in <code>char</code> - * arrays and in the <code>String</code> and <code>StringBuffer</code> - * classes. In this representation, supplementary characters are - * represented as a pair of <code>char</code> values, the first from - * the <em>high-surrogates</em> range, (\uD800-\uDBFF), the - * second from the <em>low-surrogates</em> range - * (\uDC00-\uDFFF). + * platform uses the UTF-16 representation in <code>char</code> arrays and + * in the <code>String</code> and <code>StringBuffer</code> classes. In + * this representation, supplementary characters are represented as a pair + * of <code>char</code> values, the first from the <em>high-surrogates</em> + * range, (\uD800-\uDBFF), the second from the + * <em>low-surrogates</em> range (\uDC00-\uDFFF). * * <p>A <code>char</code> value, therefore, represents Basic * Multilingual Plane (BMP) code points, including the surrogate @@ -115,10 +115,12 @@ * @author Lee Boynton * @author Guy Steele * @author Akira Tanaka + * @author Martin Buchholz + * @author Ulf Zibis * @since 1.0 */ public final -class Character extends Object implements java.io.Serializable, Comparable<Character> { +class Character implements java.io.Serializable, Comparable<Character> { /** * The minimum radix available for conversion to and from strings. * The constant value of this field is the smallest value permitted @@ -127,10 +129,10 @@ * method, and the <code>toString</code> method of class * <code>Integer</code>. * - * @see java.lang.Character#digit(char, int) - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Integer#toString(int, int) - * @see java.lang.Integer#valueOf(java.lang.String) + * @see Character#digit(char, int) + * @see Character#forDigit(int, int) + * @see Integer#toString(int, int) + * @see Integer#valueOf(String) */ public static final int MIN_RADIX = 2; @@ -142,10 +144,10 @@ * method, and the <code>toString</code> method of class * <code>Integer</code>. * - * @see java.lang.Character#digit(char, int) - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Integer#toString(int, int) - * @see java.lang.Integer#valueOf(java.lang.String) + * @see Character#digit(char, int) + * @see Character#forDigit(int, int) + * @see Integer#toString(int, int) + * @see Integer#valueOf(String) */ public static final int MAX_RADIX = 36; @@ -155,7 +157,7 @@ * * @since 1.0.2 */ - public static final char MIN_VALUE = '\u0000'; + public static final char MIN_VALUE = '\u0000'; /** * The constant value of this field is the largest value of type @@ -163,7 +165,7 @@ * * @since 1.0.2 */ - public static final char MAX_VALUE = '\uFFFF'; + public static final char MAX_VALUE = '\uFFFF'; /** * The <code>Class</code> instance representing the primitive type @@ -171,230 +173,201 @@ * * @since 1.1 */ + @SuppressWarnings("unchecked") public static final Class<Character> TYPE = Class.getPrimitiveClass("char"); - /* - * Normative general types - */ - - /* - * General character types - */ - - /** - * General category "Cn" in the Unicode specification. - * @since 1.1 - */ - public static final byte - UNASSIGNED = 0; - - /** - * General category "Lu" in the Unicode specification. - * @since 1.1 - */ - public static final byte - UPPERCASE_LETTER = 1; - - /** - * General category "Ll" in the Unicode specification. - * @since 1.1 - */ - public static final byte - LOWERCASE_LETTER = 2; - - /** - * General category "Lt" in the Unicode specification. - * @since 1.1 - */ - public static final byte - TITLECASE_LETTER = 3; - - /** - * General category "Lm" in the Unicode specification. - * @since 1.1 - */ - public static final byte - MODIFIER_LETTER = 4; - - /** - * General category "Lo" in the Unicode specification. - * @since 1.1 - */ - public static final byte - OTHER_LETTER = 5; - - /** - * General category "Mn" in the Unicode specification. - * @since 1.1 - */ - public static final byte - NON_SPACING_MARK = 6; - - /** - * General category "Me" in the Unicode specification. - * @since 1.1 - */ - public static final byte - ENCLOSING_MARK = 7; - - /** - * General category "Mc" in the Unicode specification. - * @since 1.1 - */ - public static final byte - COMBINING_SPACING_MARK = 8; - - /** - * General category "Nd" in the Unicode specification. - * @since 1.1 - */ - public static final byte - DECIMAL_DIGIT_NUMBER = 9; - - /** - * General category "Nl" in the Unicode specification. - * @since 1.1 - */ - public static final byte - LETTER_NUMBER = 10; - - /** - * General category "No" in the Unicode specification. - * @since 1.1 - */ - public static final byte - OTHER_NUMBER = 11; - - /** - * General category "Zs" in the Unicode specification. - * @since 1.1 - */ - public static final byte - SPACE_SEPARATOR = 12; - - /** - * General category "Zl" in the Unicode specification. - * @since 1.1 - */ - public static final byte - LINE_SEPARATOR = 13; - - /** - * General category "Zp" in the Unicode specification. - * @since 1.1 - */ - public static final byte - PARAGRAPH_SEPARATOR = 14; - - /** - * General category "Cc" in the Unicode specification. - * @since 1.1 - */ - public static final byte - CONTROL = 15; - - /** - * General category "Cf" in the Unicode specification. - * @since 1.1 - */ - public static final byte - FORMAT = 16; - - /** - * General category "Co" in the Unicode specification. - * @since 1.1 - */ - public static final byte - PRIVATE_USE = 18; - - /** - * General category "Cs" in the Unicode specification. - * @since 1.1 - */ - public static final byte - SURROGATE = 19; - - /** - * General category "Pd" in the Unicode specification. - * @since 1.1 - */ - public static final byte - DASH_PUNCTUATION = 20; - - /** - * General category "Ps" in the Unicode specification. - * @since 1.1 - */ - public static final byte - START_PUNCTUATION = 21; - - /** - * General category "Pe" in the Unicode specification. - * @since 1.1 - */ - public static final byte - END_PUNCTUATION = 22; - - /** - * General category "Pc" in the Unicode specification. - * @since 1.1 - */ - public static final byte - CONNECTOR_PUNCTUATION = 23; - - /** - * General category "Po" in the Unicode specification. - * @since 1.1 - */ - public static final byte - OTHER_PUNCTUATION = 24; - - /** - * General category "Sm" in the Unicode specification. - * @since 1.1 - */ - public static final byte - MATH_SYMBOL = 25; - - /** - * General category "Sc" in the Unicode specification. - * @since 1.1 - */ - public static final byte - CURRENCY_SYMBOL = 26; - - /** - * General category "Sk" in the Unicode specification. - * @since 1.1 - */ - public static final byte - MODIFIER_SYMBOL = 27; - - /** - * General category "So" in the Unicode specification. - * @since 1.1 - */ - public static final byte - OTHER_SYMBOL = 28; - - /** - * General category "Pi" in the Unicode specification. - * @since 1.4 - */ - public static final byte - INITIAL_QUOTE_PUNCTUATION = 29; - - /** - * General category "Pf" in the Unicode specification. - * @since 1.4 - */ - public static final byte - FINAL_QUOTE_PUNCTUATION = 30; + /* + * Normative general types + */ + + /* + * General character types + */ + + /** + * General category "Cn" in the Unicode specification. + * @since 1.1 + */ + public static final byte UNASSIGNED = 0; + + /** + * General category "Lu" in the Unicode specification. + * @since 1.1 + */ + public static final byte UPPERCASE_LETTER = 1; + + /** + * General category "Ll" in the Unicode specification. + * @since 1.1 + */ + public static final byte LOWERCASE_LETTER = 2; + + /** + * General category "Lt" in the Unicode specification. + * @since 1.1 + */ + public static final byte TITLECASE_LETTER = 3; + + /** + * General category "Lm" in the Unicode specification. + * @since 1.1 + */ + public static final byte MODIFIER_LETTER = 4; + + /** + * General category "Lo" in the Unicode specification. + * @since 1.1 + */ + public static final byte OTHER_LETTER = 5; + + /** + * General category "Mn" in the Unicode specification. + * @since 1.1 + */ + public static final byte NON_SPACING_MARK = 6; + + /** + * General category "Me" in the Unicode specification. + * @since 1.1 + */ + public static final byte ENCLOSING_MARK = 7; + + /** + * General category "Mc" in the Unicode specification. + * @since 1.1 + */ + public static final byte COMBINING_SPACING_MARK = 8; + + /** + * General category "Nd" in the Unicode specification. + * @since 1.1 + */ + public static final byte DECIMAL_DIGIT_NUMBER = 9; + + /** + * General category "Nl" in the Unicode specification. + * @since 1.1 + */ + public static final byte LETTER_NUMBER = 10; + + /** + * General category "No" in the Unicode specification. + * @since 1.1 + */ + public static final byte OTHER_NUMBER = 11; + + /** + * General category "Zs" in the Unicode specification. + * @since 1.1 + */ + public static final byte SPACE_SEPARATOR = 12; + + /** + * General category "Zl" in the Unicode specification. + * @since 1.1 + */ + public static final byte LINE_SEPARATOR = 13; + + /** + * General category "Zp" in the Unicode specification. + * @since 1.1 + */ + public static final byte PARAGRAPH_SEPARATOR = 14; + + /** + * General category "Cc" in the Unicode specification. + * @since 1.1 + */ + public static final byte CONTROL = 15; + + /** + * General category "Cf" in the Unicode specification. + * @since 1.1 + */ + public static final byte FORMAT = 16; + + /** + * General category "Co" in the Unicode specification. + * @since 1.1 + */ + public static final byte PRIVATE_USE = 18; + + /** + * General category "Cs" in the Unicode specification. + * @since 1.1 + */ + public static final byte SURROGATE = 19; + + /** + * General category "Pd" in the Unicode specification. + * @since 1.1 + */ + public static final byte DASH_PUNCTUATION = 20; + + /** + * General category "Ps" in the Unicode specification. + * @since 1.1 + */ + public static final byte START_PUNCTUATION = 21; + + /** + * General category "Pe" in the Unicode specification. + * @since 1.1 + */ + public static final byte END_PUNCTUATION = 22; + + /** + * General category "Pc" in the Unicode specification. + * @since 1.1 + */ + public static final byte CONNECTOR_PUNCTUATION = 23; + + /** + * General category "Po" in the Unicode specification. + * @since 1.1 + */ + public static final byte OTHER_PUNCTUATION = 24; + + /** + * General category "Sm" in the Unicode specification. + * @since 1.1 + */ + public static final byte MATH_SYMBOL = 25; + + /** + * General category "Sc" in the Unicode specification. + * @since 1.1 + */ + public static final byte CURRENCY_SYMBOL = 26; + + /** + * General category "Sk" in the Unicode specification. + * @since 1.1 + */ + public static final byte MODIFIER_SYMBOL = 27; + + /** + * General category "So" in the Unicode specification. + * @since 1.1 + */ + public static final byte OTHER_SYMBOL = 28; + + /** + * General category "Pi" in the Unicode specification. + * @since 1.4 + */ + public static final byte INITIAL_QUOTE_PUNCTUATION = 29; + + /** + * General category "Pf" in the Unicode specification. + * @since 1.4 + */ + public static final byte FINAL_QUOTE_PUNCTUATION = 30; /** * Error flag. Use int (code point) to avoid confusion with U+FFFF. */ - static final int ERROR = 0xFFFFFFFF; + static final int ERROR = 0xFFFFFFFF; /** @@ -402,7 +375,7 @@ * values have undefined directionality in the Unicode specification. * @since 1.4 */ - public static final byte DIRECTIONALITY_UNDEFINED = -1; + public static final byte DIRECTIONALITY_UNDEFINED = -1; /** * Strong bidirectional character type "L" in the Unicode specification. @@ -609,9 +582,9 @@ /** * Instances of this class represent particular subsets of the Unicode * character set. The only family of subsets defined in the - * <code>Character</code> class is <code>{@link Character.UnicodeBlock - * UnicodeBlock}</code>. Other portions of the Java API may define other - * subsets for their own purposes. + * <code>Character</code> class is {@link Character.UnicodeBlock}. + * Other portions of the Java API may define other subsets for their + * own purposes. * * @since 1.2 */ @@ -624,6 +597,7 @@ * * @exception NullPointerException if name is <code>null</code> * @param name The name of this subset + * @exception NullPointerException if name is <code>null</code> */ protected Subset(String name) { if (name == null) { @@ -662,6 +636,9 @@ } } + // See http://www.unicode.org/Public/UNIDATA/Blocks.txt + // for the latest specification of Unicode Blocks. + /** * A family of character subsets representing the character blocks in the * Unicode specification. Character blocks generally define characters @@ -672,37 +649,35 @@ */ public static final class UnicodeBlock extends Subset { - private static Map map = new HashMap(); - - /** - * Create a UnicodeBlock with the given identifier name. + private static Map<String, UnicodeBlock> map + = new HashMap<String, UnicodeBlock>(256); + + /** + * Creates a UnicodeBlock with the given identifier name. * This name must be the same as the block identifier. */ private UnicodeBlock(String idName) { super(idName); - map.put(idName.toUpperCase(Locale.US), this); + map.put(idName, this); } /** - * Create a UnicodeBlock with the given identifier name and + * Creates a UnicodeBlock with the given identifier name and * alias name. */ private UnicodeBlock(String idName, String alias) { this(idName); - map.put(alias.toUpperCase(Locale.US), this); + map.put(alias, this); } /** - * Create a UnicodeBlock with the given identifier name and + * Creates a UnicodeBlock with the given identifier name and * alias names. */ - private UnicodeBlock(String idName, String[] aliasName) { + private UnicodeBlock(String idName, String... aliases) { this(idName); - if (aliasName != null) { - for(int x=0; x<aliasName.length; ++x) { - map.put(aliasName[x].toUpperCase(Locale.US), this); - } - } + for (String alias : aliases) + map.put(alias, this); } /** @@ -710,51 +685,63 @@ * @since 1.2 */ public static final UnicodeBlock BASIC_LATIN = - new UnicodeBlock("BASIC_LATIN", new String[] {"Basic Latin", "BasicLatin" }); + new UnicodeBlock("BASIC_LATIN", + "BASIC LATIN", + "BASICLATIN"); /** * Constant for the "Latin-1 Supplement" Unicode character block. * @since 1.2 */ public static final UnicodeBlock LATIN_1_SUPPLEMENT = - new UnicodeBlock("LATIN_1_SUPPLEMENT", new String[]{ "Latin-1 Supplement", "Latin-1Supplement"}); + new UnicodeBlock("LATIN_1_SUPPLEMENT", + "LATIN-1 SUPPLEMENT", + "LATIN-1SUPPLEMENT"); /** * Constant for the "Latin Extended-A" Unicode character block. * @since 1.2 */ public static final UnicodeBlock LATIN_EXTENDED_A = - new UnicodeBlock("LATIN_EXTENDED_A", new String[]{ "Latin Extended-A", "LatinExtended-A"}); + new UnicodeBlock("LATIN_EXTENDED_A", + "LATIN EXTENDED-A", + "LATINEXTENDED-A"); /** * Constant for the "Latin Extended-B" Unicode character block. * @since 1.2 */ public static final UnicodeBlock LATIN_EXTENDED_B = - new UnicodeBlock("LATIN_EXTENDED_B", new String[] {"Latin Extended-B", "LatinExtended-B"}); + new UnicodeBlock("LATIN_EXTENDED_B", + "LATIN EXTENDED-B", + "LATINEXTENDED-B"); /** * Constant for the "IPA Extensions" Unicode character block. * @since 1.2 */ public static final UnicodeBlock IPA_EXTENSIONS = - new UnicodeBlock("IPA_EXTENSIONS", new String[] {"IPA Extensions", "IPAExtensions"}); + new UnicodeBlock("IPA_EXTENSIONS", + "IPA EXTENSIONS", + "IPAEXTENSIONS"); /** * Constant for the "Spacing Modifier Letters" Unicode character block. * @since 1.2 */ public static final UnicodeBlock SPACING_MODIFIER_LETTERS = - new UnicodeBlock("SPACING_MODIFIER_LETTERS", new String[] { "Spacing Modifier Letters", - "SpacingModifierLetters"}); + new UnicodeBlock("SPACING_MODIFIER_LETTERS", + "SPACING MODIFIER LETTERS", + "SPACINGMODIFIERLETTERS"); /** * Constant for the "Combining Diacritical Marks" Unicode character block. * @since 1.2 */ public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = - new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", new String[] {"Combining Diacritical Marks", - "CombiningDiacriticalMarks" }); + new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", + "COMBINING DIACRITICAL MARKS", + "COMBININGDIACRITICALMARKS"); /** * Constant for the "Greek and Coptic" Unicode character block. @@ -763,8 +750,10 @@ * * @since 1.2 */ - public static final UnicodeBlock GREEK - = new UnicodeBlock("GREEK", new String[] {"Greek and Coptic", "GreekandCoptic"}); + public static final UnicodeBlock GREEK = + new UnicodeBlock("GREEK", + "GREEK AND COPTIC", + "GREEKANDCOPTIC"); /** * Constant for the "Cyrillic" Unicode character block. @@ -890,44 +879,54 @@ * @since 1.2 */ public static final UnicodeBlock HANGUL_JAMO = - new UnicodeBlock("HANGUL_JAMO", new String[] {"Hangul Jamo", "HangulJamo"}); + new UnicodeBlock("HANGUL_JAMO", + "HANGUL JAMO", + "HANGULJAMO"); /** * Constant for the "Latin Extended Additional" Unicode character block. * @since 1.2 */ public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = - new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", new String[] {"Latin Extended Additional", - "LatinExtendedAdditional"}); + new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", + "LATIN EXTENDED ADDITIONAL", + "LATINEXTENDEDADDITIONAL"); /** * Constant for the "Greek Extended" Unicode character block. * @since 1.2 */ public static final UnicodeBlock GREEK_EXTENDED = - new UnicodeBlock("GREEK_EXTENDED", new String[] {"Greek Extended", "GreekExtended"}); + new UnicodeBlock("GREEK_EXTENDED", + "GREEK EXTENDED", + "GREEKEXTENDED"); /** * Constant for the "General Punctuation" Unicode character block. * @since 1.2 */ public static final UnicodeBlock GENERAL_PUNCTUATION = - new UnicodeBlock("GENERAL_PUNCTUATION", new String[] {"General Punctuation", "GeneralPunctuation"}); + new UnicodeBlock("GENERAL_PUNCTUATION", + "GENERAL PUNCTUATION", + "GENERALPUNCTUATION"); /** * Constant for the "Superscripts and Subscripts" Unicode character block. * @since 1.2 */ public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = - new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", new String[] {"Superscripts and Subscripts", - "SuperscriptsandSubscripts" }); + new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", + "SUPERSCRIPTS AND SUBSCRIPTS", + "SUPERSCRIPTSANDSUBSCRIPTS"); /** * Constant for the "Currency Symbols" Unicode character block. * @since 1.2 */ public static final UnicodeBlock CURRENCY_SYMBOLS = - new UnicodeBlock("CURRENCY_SYMBOLS", new String[] { "Currency Symbols", "CurrencySymbols"}); + new UnicodeBlock("CURRENCY_SYMBOLS", + "CURRENCY SYMBOLS", + "CURRENCYSYMBOLS"); /** * Constant for the "Combining Diacritical Marks for Symbols" Unicode character block. @@ -936,24 +935,29 @@ * @since 1.2 */ public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = - new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", new String[] {"Combining Diacritical Marks for Symbols", - "CombiningDiacriticalMarksforSymbols", - "Combining Marks for Symbols", - "CombiningMarksforSymbols" }); + new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", + "COMBINING DIACRITICAL MARKS FOR SYMBOLS", + "COMBININGDIACRITICALMARKSFORSYMBOLS", + "COMBINING MARKS FOR SYMBOLS", + "COMBININGMARKSFORSYMBOLS"); /** * Constant for the "Letterlike Symbols" Unicode character block. * @since 1.2 */ public static final UnicodeBlock LETTERLIKE_SYMBOLS = - new UnicodeBlock("LETTERLIKE_SYMBOLS", new String[] { "Letterlike Symbols", "LetterlikeSymbols"}); + new UnicodeBlock("LETTERLIKE_SYMBOLS", + "LETTERLIKE SYMBOLS", + "LETTERLIKESYMBOLS"); /** * Constant for the "Number Forms" Unicode character block. * @since 1.2 */ public static final UnicodeBlock NUMBER_FORMS = - new UnicodeBlock("NUMBER_FORMS", new String[] {"Number Forms", "NumberForms"}); + new UnicodeBlock("NUMBER_FORMS", + "NUMBER FORMS", + "NUMBERFORMS"); /** * Constant for the "Arrows" Unicode character block. @@ -967,68 +971,81 @@ * @since 1.2 */ public static final UnicodeBlock MATHEMATICAL_OPERATORS = - new UnicodeBlock("MATHEMATICAL_OPERATORS", new String[] {"Mathematical Operators", - "MathematicalOperators"}); + new UnicodeBlock("MATHEMATICAL_OPERATORS", + "MATHEMATICAL OPERATORS", + "MATHEMATICALOPERATORS"); /** * Constant for the "Miscellaneous Technical" Unicode character block. * @since 1.2 */ public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = - new UnicodeBlock("MISCELLANEOUS_TECHNICAL", new String[] {"Miscellaneous Technical", - "MiscellaneousTechnical"}); + new UnicodeBlock("MISCELLANEOUS_TECHNICAL", + "MISCELLANEOUS TECHNICAL", + "MISCELLANEOUSTECHNICAL"); /** * Constant for the "Control Pictures" Unicode character block. * @since 1.2 */ public static final UnicodeBlock CONTROL_PICTURES = - new UnicodeBlock("CONTROL_PICTURES", new String[] {"Control Pictures", "ControlPictures"}); + new UnicodeBlock("CONTROL_PICTURES", + "CONTROL PICTURES", + "CONTROLPICTURES"); /** * Constant for the "Optical Character Recognition" Unicode character block. * @since 1.2 */ public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = - new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", new String[] {"Optical Character Recognition", - "OpticalCharacterRecognition"}); + new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", + "OPTICAL CHARACTER RECOGNITION", + "OPTICALCHARACTERRECOGNITION"); /** * Constant for the "Enclosed Alphanumerics" Unicode character block. * @since 1.2 */ public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = - new UnicodeBlock("ENCLOSED_ALPHANUMERICS", new String[] {"Enclosed Alphanumerics", - "EnclosedAlphanumerics"}); + new UnicodeBlock("ENCLOSED_ALPHANUMERICS", + "ENCLOSED ALPHANUMERICS", + "ENCLOSEDALPHANUMERICS"); /** * Constant for the "Box Drawing" Unicode character block. * @since 1.2 */ public static final UnicodeBlock BOX_DRAWING = - new UnicodeBlock("BOX_DRAWING", new String[] {"Box Drawing", "BoxDrawing"}); + new UnicodeBlock("BOX_DRAWING", + "BOX DRAWING", + "BOXDRAWING"); /** * Constant for the "Block Elements" Unicode character block. * @since 1.2 */ public static final UnicodeBlock BLOCK_ELEMENTS = - new UnicodeBlock("BLOCK_ELEMENTS", new String[] {"Block Elements", "BlockElements"}); + new UnicodeBlock("BLOCK_ELEMENTS", + "BLOCK ELEMENTS", + "BLOCKELEMENTS"); /** * Constant for the "Geometric Shapes" Unicode character block. * @since 1.2 */ public static final UnicodeBlock GEOMETRIC_SHAPES = - new UnicodeBlock("GEOMETRIC_SHAPES", new String[] {"Geometric Shapes", "GeometricShapes"}); + new UnicodeBlock("GEOMETRIC_SHAPES", + "GEOMETRIC SHAPES", + "GEOMETRICSHAPES"); /** * Constant for the "Miscellaneous Symbols" Unicode character block. * @since 1.2 */ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = - new UnicodeBlock("MISCELLANEOUS_SYMBOLS", new String[] {"Miscellaneous Symbols", - "MiscellaneousSymbols"}); + new UnicodeBlock("MISCELLANEOUS_SYMBOLS", + "MISCELLANEOUS SYMBOLS", + "MISCELLANEOUSSYMBOLS"); /** * Constant for the "Dingbats" Unicode character block. @@ -1042,8 +1059,9 @@ * @since 1.2 */ public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = - new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", new String[] {"CJK Symbols and Punctuation", - "CJKSymbolsandPunctuation"}); + new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", + "CJK SYMBOLS AND PUNCTUATION", + "CJKSYMBOLSANDPUNCTUATION"); /** * Constant for the "Hiragana" Unicode character block. @@ -1071,8 +1089,9 @@ * @since 1.2 */ public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = - new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", new String[] {"Hangul Compatibility Jamo", - "HangulCompatibilityJamo"}); + new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", + "HANGUL COMPATIBILITY JAMO", + "HANGULCOMPATIBILITYJAMO"); /** * Constant for the "Kanbun" Unicode character block. @@ -1086,37 +1105,45 @@ * @since 1.2 */ public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = - new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", new String[] {"Enclosed CJK Letters and Months", - "EnclosedCJKLettersandMonths"}); + new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", + "ENCLOSED CJK LETTERS AND MONTHS", + "ENCLOSEDCJKLETTERSANDMONTHS"); /** * Constant for the "CJK Compatibility" Unicode character block. * @since 1.2 */ public static final UnicodeBlock CJK_COMPATIBILITY = - new UnicodeBlock("CJK_COMPATIBILITY", new String[] {"CJK Compatibility", "CJKCompatibility"}); + new UnicodeBlock("CJK_COMPATIBILITY", + "CJK COMPATIBILITY", + "CJKCOMPATIBILITY"); /** * Constant for the "CJK Unified Ideographs" Unicode character block. * @since 1.2 */ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = - new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", new String[] {"CJK Unified Ideographs", - "CJKUnifiedIdeographs"}); + new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", + "CJK UNIFIED IDEOGRAPHS", + "CJKUNIFIEDIDEOGRAPHS"); /** * Constant for the "Hangul Syllables" Unicode character block. * @since 1.2 */ public static final UnicodeBlock HANGUL_SYLLABLES = - new UnicodeBlock("HANGUL_SYLLABLES", new String[] {"Hangul Syllables", "HangulSyllables"}); + new UnicodeBlock("HANGUL_SYLLABLES", + "HANGUL SYLLABLES", + "HANGULSYLLABLES"); /** * Constant for the "Private Use Area" Unicode character block. * @since 1.2 */ public static final UnicodeBlock PRIVATE_USE_AREA = - new UnicodeBlock("PRIVATE_USE_AREA", new String[] {"Private Use Area", "PrivateUseArea"}); + new UnicodeBlock("PRIVATE_USE_AREA", + "PRIVATE USE AREA", + "PRIVATEUSEAREA"); /** * Constant for the "CJK Compatibility Ideographs" Unicode character block. @@ -1124,56 +1151,62 @@ */ public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", - new String[] {"CJK Compatibility Ideographs", - "CJKCompatibilityIdeographs"}); + "CJK COMPATIBILITY IDEOGRAPHS", + "CJKCOMPATIBILITYIDEOGRAPHS"); /** * Constant for the "Alphabetic Presentation Forms" Unicode character block. * @since 1.2 */ public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = - new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", new String[] {"Alphabetic Presentation Forms", - "AlphabeticPresentationForms"}); + new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", + "ALPHABETIC PRESENTATION FORMS", + "ALPHABETICPRESENTATIONFORMS"); /** * Constant for the "Arabic Presentation Forms-A" Unicode character block. * @since 1.2 */ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = - new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", new String[] {"Arabic Presentation Forms-A", - "ArabicPresentationForms-A"}); + new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", + "ARABIC PRESENTATION FORMS-A", + "ARABICPRESENTATIONFORMS-A"); /** * Constant for the "Combining Half Marks" Unicode character block. * @since 1.2 */ public static final UnicodeBlock COMBINING_HALF_MARKS = - new UnicodeBlock("COMBINING_HALF_MARKS", new String[] {"Combining Half Marks", - "CombiningHalfMarks"}); + new UnicodeBlock("COMBINING_HALF_MARKS", + "COMBINING HALF MARKS", + "COMBININGHALFMARKS"); /** * Constant for the "CJK Compatibility Forms" Unicode character block. * @since 1.2 */ public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = - new UnicodeBlock("CJK_COMPATIBILITY_FORMS", new String[] {"CJK Compatibility Forms", - "CJKCompatibilityForms"}); + new UnicodeBlock("CJK_COMPATIBILITY_FORMS", + "CJK COMPATIBILITY FORMS", + "CJKCOMPATIBILITYFORMS"); /** * Constant for the "Small Form Variants" Unicode character block. * @since 1.2 */ public static final UnicodeBlock SMALL_FORM_VARIANTS = - new UnicodeBlock("SMALL_FORM_VARIANTS", new String[] {"Small Form Variants", - "SmallFormVariants"}); + new UnicodeBlock("SMALL_FORM_VARIANTS", + "SMALL FORM VARIANTS", + "SMALLFORMVARIANTS"); /** * Constant for the "Arabic Presentation Forms-B" Unicode character block. * @since 1.2 */ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = - new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", new String[] {"Arabic Presentation Forms-B", - "ArabicPresentationForms-B"}); + new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", + "ARABIC PRESENTATION FORMS-B", + "ARABICPRESENTATIONFORMS-B"); /** * Constant for the "Halfwidth and Fullwidth Forms" Unicode character block. @@ -1181,8 +1214,8 @@ */ public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", - new String[] {"Halfwidth and Fullwidth Forms", - "HalfwidthandFullwidthForms"}); + "HALFWIDTH AND FULLWIDTH FORMS", + "HALFWIDTHANDFULLWIDTHFORMS"); /** * Constant for the "Specials" Unicode character block. @@ -1251,97 +1284,108 @@ */ public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", - new String[] {"Unified Canadian Aboriginal Syllabics", - "UnifiedCanadianAboriginalSyllabics"}); + "UNIFIED CANADIAN ABORIGINAL SYLLABICS", + "UNIFIEDCANADIANABORIGINALSYLLABICS"); /** * Constant for the "Ogham" Unicode character block. * @since 1.4 */ public static final UnicodeBlock OGHAM = - new UnicodeBlock("OGHAM"); + new UnicodeBlock("OGHAM"); /** * Constant for the "Runic" Unicode character block. * @since 1.4 */ public static final UnicodeBlock RUNIC = - new UnicodeBlock("RUNIC"); + new UnicodeBlock("RUNIC"); /** * Constant for the "Khmer" Unicode character block. * @since 1.4 */ public static final UnicodeBlock KHMER = - new UnicodeBlock("KHMER"); + new UnicodeBlock("KHMER"); /** * Constant for the "Mongolian" Unicode character block. * @since 1.4 */ public static final UnicodeBlock MONGOLIAN = - new UnicodeBlock("MONGOLIAN"); + new UnicodeBlock("MONGOLIAN"); /** * Constant for the "Braille Patterns" Unicode character block. * @since 1.4 */ public static final UnicodeBlock BRAILLE_PATTERNS = - new UnicodeBlock("BRAILLE_PATTERNS", new String[] {"Braille Patterns", - "BraillePatterns"}); + new UnicodeBlock("BRAILLE_PATTERNS", + "BRAILLE PATTERNS", + "BRAILLEPATTERNS"); /** * Constant for the "CJK Radicals Supplement" Unicode character block. * @since 1.4 */ public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = - new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", new String[] {"CJK Radicals Supplement", - "CJKRadicalsSupplement"}); + new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", + "CJK RADICALS SUPPLEMENT", + "CJKRADICALSSUPPLEMENT"); /** * Constant for the "Kangxi Radicals" Unicode character block. * @since 1.4 */ public static final UnicodeBlock KANGXI_RADICALS = - new UnicodeBlock("KANGXI_RADICALS", new String[] {"Kangxi Radicals", "KangxiRadicals"}); + new UnicodeBlock("KANGXI_RADICALS", + "KANGXI RADICALS", + "KANGXIRADICALS"); /** * Constant for the "Ideographic Description Characters" Unicode character block. * @since 1.4 */ public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = - new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", new String[] {"Ideographic Description Characters", - "IdeographicDescriptionCharacters"}); + new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", + "IDEOGRAPHIC DESCRIPTION CHARACTERS", + "IDEOGRAPHICDESCRIPTIONCHARACTERS"); /** * Constant for the "Bopomofo Extended" Unicode character block. * @since 1.4 */ public static final UnicodeBlock BOPOMOFO_EXTENDED = - new UnicodeBlock("BOPOMOFO_EXTENDED", new String[] {"Bopomofo Extended", - "BopomofoExtended"}); + new UnicodeBlock("BOPOMOFO_EXTENDED", + "BOPOMOFO EXTENDED", + "BOPOMOFOEXTENDED"); /** * Constant for the "CJK Unified Ideographs Extension A" Unicode character block. * @since 1.4 */ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = - new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", new String[] {"CJK Unified Ideographs Extension A", - "CJKUnifiedIdeographsExtensionA"}); + new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", + "CJK UNIFIED IDEOGRAPHS EXTENSION A", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONA"); /** * Constant for the "Yi Syllables" Unicode character block. * @since 1.4 */ public static final UnicodeBlock YI_SYLLABLES = - new UnicodeBlock("YI_SYLLABLES", new String[] {"Yi Syllables", "YiSyllables"}); + new UnicodeBlock("YI_SYLLABLES", + "YI SYLLABLES", + "YISYLLABLES"); /** * Constant for the "Yi Radicals" Unicode character block. * @since 1.4 */ public static final UnicodeBlock YI_RADICALS = - new UnicodeBlock("YI_RADICALS", new String[] {"Yi Radicals", "YiRadicals"}); + new UnicodeBlock("YI_RADICALS", + "YI RADICALS", + "YIRADICALS"); /** @@ -1350,10 +1394,10 @@ */ public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", - new String[] {"Cyrillic Supplementary", - "CyrillicSupplementary", - "Cyrillic Supplement", - "CyrillicSupplement"}); + "CYRILLIC SUPPLEMENTARY", + "CYRILLICSUPPLEMENTARY", + "CYRILLIC SUPPLEMENT", + "CYRILLICSUPPLEMENT"); /** * Constant for the "Tagalog" Unicode character block. @@ -1395,21 +1439,27 @@ * @since 1.5 */ public static final UnicodeBlock TAI_LE = - new UnicodeBlock("TAI_LE", new String[] {"Tai Le", "TaiLe"}); + new UnicodeBlock("TAI_LE", + "TAI LE", + "TAILE"); /** * Constant for the "Khmer Symbols" Unicode character block. * @since 1.5 */ public static final UnicodeBlock KHMER_SYMBOLS = - new UnicodeBlock("KHMER_SYMBOLS", new String[] {"Khmer Symbols", "KhmerSymbols"}); + new UnicodeBlock("KHMER_SYMBOLS", + "KHMER SYMBOLS", + "KHMERSYMBOLS"); /** * Constant for the "Phonetic Extensions" Unicode character block. * @since 1.5 */ public static final UnicodeBlock PHONETIC_EXTENSIONS = - new UnicodeBlock("PHONETIC_EXTENSIONS", new String[] {"Phonetic Extensions", "PhoneticExtensions"}); + new UnicodeBlock("PHONETIC_EXTENSIONS", + "PHONETIC EXTENSIONS", + "PHONETICEXTENSIONS"); /** * Constant for the "Miscellaneous Mathematical Symbols-A" Unicode character block. @@ -1417,33 +1467,35 @@ */ public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", - new String[]{"Miscellaneous Mathematical Symbols-A", - "MiscellaneousMathematicalSymbols-A"}); + "MISCELLANEOUS MATHEMATICAL SYMBOLS-A", + "MISCELLANEOUSMATHEMATICALSYMBOLS-A"); /** * Constant for the "Supplemental Arrows-A" Unicode character block. * @since 1.5 */ public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = - new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", new String[] {"Supplemental Arrows-A", - "SupplementalArrows-A"}); + new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", + "SUPPLEMENTAL ARROWS-A", + "SUPPLEMENTALARROWS-A"); /** * Constant for the "Supplemental Arrows-B" Unicode character block. * @since 1.5 */ public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = - new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", new String[] {"Supplemental Arrows-B", - "SupplementalArrows-B"}); + new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", + "SUPPLEMENTAL ARROWS-B", + "SUPPLEMENTALARROWS-B"); /** * Constant for the "Miscellaneous Mathematical Symbols-B" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B - = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", - new String[] {"Miscellaneous Mathematical Symbols-B", - "MiscellaneousMathematicalSymbols-B"}); + public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = + new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", + "MISCELLANEOUS MATHEMATICAL SYMBOLS-B", + "MISCELLANEOUSMATHEMATICALSYMBOLS-B"); /** * Constant for the "Supplemental Mathematical Operators" Unicode character block. @@ -1451,127 +1503,151 @@ */ public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", - new String[]{"Supplemental Mathematical Operators", - "SupplementalMathematicalOperators"} ); + "SUPPLEMENTAL MATHEMATICAL OPERATORS", + "SUPPLEMENTALMATHEMATICALOPERATORS"); /** * Constant for the "Miscellaneous Symbols and Arrows" Unicode character block. * @since 1.5 */ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = - new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", new String[] {"Miscellaneous Symbols and Arrows", - "MiscellaneousSymbolsandArrows"}); + new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", + "MISCELLANEOUS SYMBOLS AND ARROWS", + "MISCELLANEOUSSYMBOLSANDARROWS"); /** * Constant for the "Katakana Phonetic Extensions" Unicode character block. * @since 1.5 */ public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = - new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", new String[] {"Katakana Phonetic Extensions", - "KatakanaPhoneticExtensions"}); + new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", + "KATAKANA PHONETIC EXTENSIONS", + "KATAKANAPHONETICEXTENSIONS"); /** * Constant for the "Yijing Hexagram Symbols" Unicode character block. * @since 1.5 */ public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = - new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", new String[] {"Yijing Hexagram Symbols", - "YijingHexagramSymbols"}); + new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", + "YIJING HEXAGRAM SYMBOLS", + "YIJINGHEXAGRAMSYMBOLS"); /** * Constant for the "Variation Selectors" Unicode character block. * @since 1.5 */ public static final UnicodeBlock VARIATION_SELECTORS = - new UnicodeBlock("VARIATION_SELECTORS", new String[] {"Variation Selectors", "VariationSelectors"}); + new UnicodeBlock("VARIATION_SELECTORS", + "VARIATION SELECTORS", + "VARIATIONSELECTORS"); /** * Constant for the "Linear B Syllabary" Unicode character block. * @since 1.5 */ public static final UnicodeBlock LINEAR_B_SYLLABARY = - new UnicodeBlock("LINEAR_B_SYLLABARY", new String[] {"Linear B Syllabary", "LinearBSyllabary"}); + new UnicodeBlock("LINEAR_B_SYLLABARY", + "LINEAR B SYLLABARY", + "LINEARBSYLLABARY"); /** * Constant for the "Linear B Ideograms" Unicode character block. * @since 1.5 */ public static final UnicodeBlock LINEAR_B_IDEOGRAMS = - new UnicodeBlock("LINEAR_B_IDEOGRAMS", new String[] {"Linear B Ideograms", "LinearBIdeograms"}); + new UnicodeBlock("LINEAR_B_IDEOGRAMS", + "LINEAR B IDEOGRAMS", + "LINEARBIDEOGRAMS"); /** * Constant for the "Aegean Numbers" Unicode character block. * @since 1.5 */ public static final UnicodeBlock AEGEAN_NUMBERS = - new UnicodeBlock("AEGEAN_NUMBERS", new String[] {"Aegean Numbers", "AegeanNumbers"}); + new UnicodeBlock("AEGEAN_NUMBERS", + "AEGEAN NUMBERS", + "AEGEANNUMBERS"); /** * Constant for the "Old Italic" Unicode character block. * @since 1.5 */ public static final UnicodeBlock OLD_ITALIC = - new UnicodeBlock("OLD_ITALIC", new String[] {"Old Italic", "OldItalic"}); + new UnicodeBlock("OLD_ITALIC", + "OLD ITALIC", + "OLDITALIC"); /** * Constant for the "Gothic" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC"); + public static final UnicodeBlock GOTHIC = + new UnicodeBlock("GOTHIC"); /** * Constant for the "Ugaritic" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC"); + public static final UnicodeBlock UGARITIC = + new UnicodeBlock("UGARITIC"); /** * Constant for the "Deseret" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET"); + public static final UnicodeBlock DESERET = + new UnicodeBlock("DESERET"); /** * Constant for the "Shavian" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN"); + public static final UnicodeBlock SHAVIAN = + new UnicodeBlock("SHAVIAN"); /** * Constant for the "Osmanya" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA"); + public static final UnicodeBlock OSMANYA = + new UnicodeBlock("OSMANYA"); /** * Constant for the "Cypriot Syllabary" Unicode character block. * @since 1.5 */ public static final UnicodeBlock CYPRIOT_SYLLABARY = - new UnicodeBlock("CYPRIOT_SYLLABARY", new String[] {"Cypriot Syllabary", "CypriotSyllabary"}); + new UnicodeBlock("CYPRIOT_SYLLABARY", + "CYPRIOT SYLLABARY", + "CYPRIOTSYLLABARY"); /** * Constant for the "Byzantine Musical Symbols" Unicode character block. * @since 1.5 */ public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = - new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", new String[] {"Byzantine Musical Symbols", - "ByzantineMusicalSymbols"}); + new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", + "BYZANTINE MUSICAL SYMBOLS", + "BYZANTINEMUSICALSYMBOLS"); /** * Constant for the "Musical Symbols" Unicode character block. * @since 1.5 */ public static final UnicodeBlock MUSICAL_SYMBOLS = - new UnicodeBlock("MUSICAL_SYMBOLS", new String[] {"Musical Symbols", "MusicalSymbols"}); + new UnicodeBlock("MUSICAL_SYMBOLS", + "MUSICAL SYMBOLS", + "MUSICALSYMBOLS"); /** * Constant for the "Tai Xuan Jing Symbols" Unicode character block. * @since 1.5 */ public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = - new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", new String[] {"Tai Xuan Jing Symbols", - "TaiXuanJingSymbols"}); + new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", + "TAI XUAN JING SYMBOLS", + "TAIXUANJINGSYMBOLS"); /** * Constant for the "Mathematical Alphanumeric Symbols" Unicode character block. @@ -1579,7 +1655,8 @@ */ public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", - new String[] {"Mathematical Alphanumeric Symbols", "MathematicalAlphanumericSymbols"}); + "MATHEMATICAL ALPHANUMERIC SYMBOLS", + "MATHEMATICALALPHANUMERICSYMBOLS"); /** * Constant for the "CJK Unified Ideographs Extension B" Unicode character block. @@ -1587,7 +1664,8 @@ */ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", - new String[] {"CJK Unified Ideographs Extension B", "CJKUnifiedIdeographsExtensionB"}); + "CJK UNIFIED IDEOGRAPHS EXTENSION B", + "CJKUNIFIEDIDEOGRAPHSEXTENSIONB"); /** * Constant for the "CJK Compatibility Ideographs Supplement" Unicode character block. @@ -1595,22 +1673,24 @@ */ public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", - new String[]{"CJK Compatibility Ideographs Supplement", - "CJKCompatibilityIdeographsSupplement"}); + "CJK COMPATIBILITY IDEOGRAPHS SUPPLEMENT", + "CJKCOMPATIBILITYIDEOGRAPHSSUPPLEMENT"); /** * Constant for the "Tags" Unicode character block. * @since 1.5 */ - public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS"); + public static final UnicodeBlock TAGS = + new UnicodeBlock("TAGS"); /** * Constant for the "Variation Selectors Supplement" Unicode character block. * @since 1.5 */ public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = - new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", new String[] {"Variation Selectors Supplement", - "VariationSelectorsSupplement"}); + new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", + "VARIATION SELECTORS SUPPLEMENT", + "VARIATIONSELECTORSSUPPLEMENT"); /** * Constant for the "Supplementary Private Use Area-A" Unicode character block. @@ -1618,8 +1698,8 @@ */ public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", - new String[] {"Supplementary Private Use Area-A", - "SupplementaryPrivateUseArea-A"}); + "SUPPLEMENTARY PRIVATE USE AREA-A", + "SUPPLEMENTARYPRIVATEUSEAREA-A"); /** * Constant for the "Supplementary Private Use Area-B" Unicode character block. @@ -1627,39 +1707,44 @@ */ public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", - new String[] {"Supplementary Private Use Area-B", - "SupplementaryPrivateUseArea-B"}); + "SUPPLEMENTARY PRIVATE USE AREA-B", + "SUPPLEMENTARYPRIVATEUSEAREA-B"); /** * Constant for the "High Surrogates" Unicode character block. * This block represents codepoint values in the high surrogate - * range: 0xD800 through 0xDB7F + * range: U+D800 through U+DB7F * * @since 1.5 */ public static final UnicodeBlock HIGH_SURROGATES = - new UnicodeBlock("HIGH_SURROGATES", new String[] {"High Surrogates", "HighSurrogates"}); + new UnicodeBlock("HIGH_SURROGATES", + "HIGH SURROGATES", + "HIGHSURROGATES"); /** * Constant for the "High Private Use Surrogates" Unicode character block. - * This block represents codepoint values in the high surrogate - * range: 0xDB80 through 0xDBFF + * This block represents codepoint values in the private use high surrogate + * range: U+DB80 through U+DBFF * * @since 1.5 */ public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = - new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", new String[] { "High Private Use Surrogates", - "HighPrivateUseSurrogates"}); + new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", + "HIGH PRIVATE USE SURROGATES", + "HIGHPRIVATEUSESURROGATES"); /** * Constant for the "Low Surrogates" Unicode character block. - * This block represents codepoint values in the high surrogate - * range: 0xDC00 through 0xDFFF + * This block represents codepoint values in the low surrogate + * range: U+DC00 through U+DFFF * * @since 1.5 */ public static final UnicodeBlock LOW_SURROGATES = - new UnicodeBlock("LOW_SURROGATES", new String[] {"Low Surrogates", "LowSurrogates"}); + new UnicodeBlock("LOW_SURROGATES", + "LOW SURROGATES", + "LOWSURROGATES"); /** * Constant for the "Arabic Supplement" Unicode character block. @@ -1667,14 +1752,15 @@ */ public static final UnicodeBlock ARABIC_SUPPLEMENT = new UnicodeBlock("ARABIC_SUPPLEMENT", - new String[] { "Arabic Supplement", - "ArabicSupplement"}); + "ARABIC SUPPLEMENT", + "ARABICSUPPLEMENT"); /** * Constant for the "NKo" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock NKO = new UnicodeBlock("NKO"); + public static final UnicodeBlock NKO = + new UnicodeBlock("NKO"); /** * Constant for the "Ethiopic Supplement" Unicode character block. @@ -1682,8 +1768,8 @@ */ public static final UnicodeBlock ETHIOPIC_SUPPLEMENT = new UnicodeBlock("ETHIOPIC_SUPPLEMENT", - new String[] { "Ethiopic Supplement", - "EthiopicSupplement"}); + "ETHIOPIC SUPPLEMENT", + "ETHIOPICSUPPLEMENT"); /** * Constant for the "New Tai Lue" Unicode character block. @@ -1691,8 +1777,8 @@ */ public static final UnicodeBlock NEW_TAI_LUE = new UnicodeBlock("NEW_TAI_LUE", - new String[] { "New Tai Lue", - "NewTaiLue"}); + "NEW TAI LUE", + "NEWTAILUE"); /** * Constant for the "Buginese" Unicode character block. @@ -1719,7 +1805,8 @@ * Constant for the "Lepcha" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock LEPCHA = new UnicodeBlock("LEPCHA"); + public static final UnicodeBlock LEPCHA = + new UnicodeBlock("LEPCHA"); /** * Constant for the "Ol Chiki" Unicode character block. @@ -1727,8 +1814,8 @@ */ public static final UnicodeBlock OL_CHIKI = new UnicodeBlock("OL_CHIKI", - new String[] { "Ol Chiki", - "OlChiki"}); + "OL CHIKI", + "OLCHIKI"); /** * Constant for the "Phonetic Extensions Supplement" Unicode character @@ -1737,8 +1824,8 @@ */ public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT = new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT", - new String[] { "Phonetic Extensions Supplement", - "PhoneticExtensionsSupplement"}); + "PHONETIC EXTENSIONS SUPPLEMENT", + "PHONETICEXTENSIONSSUPPLEMENT"); /** * Constant for the "Combining Diacritical Marks Supplement" Unicode @@ -1747,8 +1834,8 @@ */ public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT", - new String[] { "Combining Diacritical Marks Supplement", - "CombiningDiacriticalMarksSupplement"}); + "COMBINING DIACRITICAL MARKS SUPPLEMENT", + "COMBININGDIACRITICALMARKSSUPPLEMENT"); /** * Constant for the "Glagolitic" Unicode character block. @@ -1763,14 +1850,15 @@ */ public static final UnicodeBlock LATIN_EXTENDED_C = new UnicodeBlock("LATIN_EXTENDED_C", - new String[] { "Latin Extended-C", - "LatinExtended-C"}); + "LATIN EXTENDED-C", + "LATINEXTENDED-C"); /** * Constant for the "Coptic" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock COPTIC = new UnicodeBlock("COPTIC"); + public static final UnicodeBlock COPTIC = + new UnicodeBlock("COPTIC"); /** * Constant for the "Georgian Supplement" Unicode character block. @@ -1778,8 +1866,8 @@ */ public static final UnicodeBlock GEORGIAN_SUPPLEMENT = new UnicodeBlock("GEORGIAN_SUPPLEMENT", - new String[] { "Georgian Supplement", - "GeorgianSupplement"}); + "GEORGIAN SUPPLEMENT", + "GEORGIANSUPPLEMENT"); /** * Constant for the "Tifinagh" Unicode character block. @@ -1794,8 +1882,8 @@ */ public static final UnicodeBlock ETHIOPIC_EXTENDED = new UnicodeBlock("ETHIOPIC_EXTENDED", - new String[] { "Ethiopic Extended", - "EthiopicExtended"}); + "ETHIOPIC EXTENDED", + "ETHIOPICEXTENDED"); /** * Constant for the "Cyrillic Extended-A" Unicode character block. @@ -1803,8 +1891,8 @@ */ public static final UnicodeBlock CYRILLIC_EXTENDED_A = new UnicodeBlock("CYRILLIC_EXTENDED_A", - new String[] { "Cyrillic Extended-A", - "CyrillicExtended-A"}); + "CYRILLIC EXTENDED-A", + "CYRILLICEXTENDED-A"); /** * Constant for the "Supplemental Punctuation" Unicode character block. @@ -1812,8 +1900,8 @@ */ public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION = new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION", - new String[] { "Supplemental Punctuation", - "SupplementalPunctuation"}); + "SUPPLEMENTAL PUNCTUATION", + "SUPPLEMENTALPUNCTUATION"); /** * Constant for the "CJK Strokes" Unicode character block. @@ -1821,14 +1909,15 @@ */ public static final UnicodeBlock CJK_STROKES = new UnicodeBlock("CJK_STROKES", - new String[] { "CJK Strokes", - "CJKStrokes"}); + "CJK STROKES", + "CJKSTROKES"); /** * Constant for the "Vai" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock VAI = new UnicodeBlock("VAI"); + public static final UnicodeBlock VAI = + new UnicodeBlock("VAI"); /** * Constant for the "Cyrillic Extended-B" Unicode character block. @@ -1836,8 +1925,8 @@ */ public static final UnicodeBlock CYRILLIC_EXTENDED_B = new UnicodeBlock("CYRILLIC_EXTENDED_B", - new String[] { "Cyrillic Extended-B", - "CyrillicExtended-B"}); + "CYRILLIC EXTENDED-B", + "CYRILLICEXTENDED-B"); /** * Constant for the "Modifier Tone Letters" Unicode character block. @@ -1845,8 +1934,8 @@ */ public static final UnicodeBlock MODIFIER_TONE_LETTERS = new UnicodeBlock("MODIFIER_TONE_LETTERS", - new String[] { "Modifier Tone Letters", - "ModifierToneLetters"}); + "MODIFIER TONE LETTERS", + "MODIFIERTONELETTERS"); /** * Constant for the "Latin Extended-D" Unicode character block. @@ -1854,8 +1943,8 @@ */ public static final UnicodeBlock LATIN_EXTENDED_D = new UnicodeBlock("LATIN_EXTENDED_D", - new String[] { "Latin Extended-D", - "LatinExtended-D"}); + "LATIN EXTENDED-D", + "LATINEXTENDED-D"); /** * Constant for the "Syloti Nagri" Unicode character block. @@ -1863,15 +1952,16 @@ */ public static final UnicodeBlock SYLOTI_NAGRI = new UnicodeBlock("SYLOTI_NAGRI", - new String[] { "Syloti Nagri", - "SylotiNagri"}); + "SYLOTI NAGRI", + "SYLOTINAGRI"); /** * Constant for the "Phags-pa" Unicode character block. * @since 1.7 */ public static final UnicodeBlock PHAGS_PA = - new UnicodeBlock("PHAGS_PA", new String[] { "Phags-pa"}); + new UnicodeBlock("PHAGS_PA", + "PHAGS-PA"); /** * Constant for the "Saurashtra" Unicode character block. @@ -1886,20 +1976,22 @@ */ public static final UnicodeBlock KAYAH_LI = new UnicodeBlock("KAYAH_LI", - new String[] { "Kayah Li", - "KayahLi"}); + "KAYAH LI", + "KAYAHLI"); /** * Constant for the "Rejang" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock REJANG = new UnicodeBlock("REJANG"); + public static final UnicodeBlock REJANG = + new UnicodeBlock("REJANG"); /** * Constant for the "Cham" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock CHAM = new UnicodeBlock("CHAM"); + public static final UnicodeBlock CHAM = + new UnicodeBlock("CHAM"); /** * Constant for the "Vertical Forms" Unicode character block. @@ -1907,8 +1999,8 @@ */ public static final UnicodeBlock VERTICAL_FORMS = new UnicodeBlock("VERTICAL_FORMS", - new String[] { "Vertical Forms", - "VerticalForms"}); + "VERTICAL FORMS", + "VERTICALFORMS"); /** * Constant for the "Ancient Greek Numbers" Unicode character block. @@ -1916,8 +2008,8 @@ */ public static final UnicodeBlock ANCIENT_GREEK_NUMBERS = new UnicodeBlock("ANCIENT_GREEK_NUMBERS", - new String[] { "Ancient Greek Numbers", - "AncientGreekNumbers"}); + "ANCIENT GREEK NUMBERS", + "ANCIENTGREEKNUMBERS"); /** * Constant for the "Ancient Symbols" Unicode character block. @@ -1925,8 +2017,8 @@ */ public static final UnicodeBlock ANCIENT_SYMBOLS = new UnicodeBlock("ANCIENT_SYMBOLS", - new String[] { "Ancient Symbols", - "AncientSymbols"}); + "ANCIENT SYMBOLS", + "ANCIENTSYMBOLS"); /** * Constant for the "Phaistos Disc" Unicode character block. @@ -1934,20 +2026,22 @@ */ public static final UnicodeBlock PHAISTOS_DISC = new UnicodeBlock("PHAISTOS_DISC", - new String[] { "Phaistos Disc", - "PhaistosDisc"}); + "PHAISTOS DISC", + "PHAISTOSDISC"); /** * Constant for the "Lycian" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock LYCIAN = new UnicodeBlock("LYCIAN"); + public static final UnicodeBlock LYCIAN = + new UnicodeBlock("LYCIAN"); /** * Constant for the "Carian" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock CARIAN = new UnicodeBlock("CARIAN"); + public static final UnicodeBlock CARIAN = + new UnicodeBlock("CARIAN"); /** * Constant for the "Old Persian" Unicode character block. @@ -1955,8 +2049,8 @@ */ public static final UnicodeBlock OLD_PERSIAN = new UnicodeBlock("OLD_PERSIAN", - new String[] { "Old Persian", - "OldPersian"}); + "OLD PERSIAN", + "OLDPERSIAN"); /** * Constant for the "Phoenician" Unicode character block. @@ -1969,7 +2063,8 @@ * Constant for the "Lydian" Unicode character block. * @since 1.7 */ - public static final UnicodeBlock LYDIAN = new UnicodeBlock("LYDIAN"); + public static final UnicodeBlock LYDIAN = + new UnicodeBlock("LYDIAN"); /** * Constant for the "Kharoshthi" Unicode character block. @@ -1992,8 +2087,8 @@ */ public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION = new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION", - new String[] { "Cuneiform Numbers and Punctuation", - "CuneiformNumbersandPunctuation"}); + "CUNEIFORM NUMBERS AND PUNCTUATION", + "CUNEIFORMNUMBERSANDPUNCTUATION"); /** * Constant for the "Ancient Greek Musical Notation" Unicode character @@ -2002,8 +2097,8 @@ */ public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION = new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION", - new String[] { "Ancient Greek Musical Notation", - "AncientGreekMusicalNotation"}); + "ANCIENT GREEK MUSICAL NOTATION", + "ANCIENTGREEKMUSICALNOTATION"); /** * Constant for the "Counting Rod Numerals" Unicode character block. @@ -2011,8 +2106,8 @@ */ public static final UnicodeBlock COUNTING_ROD_NUMERALS = new UnicodeBlock("COUNTING_ROD_NUMERALS", - new String[] { "Counting Rod Numerals", - "CountingRodNumerals"}); + "COUNTING ROD NUMERALS", + "COUNTINGRODNUMERALS"); /** * Constant for the "Mahjong Tiles" Unicode character block. @@ -2020,8 +2115,8 @@ */ public static final UnicodeBlock MAHJONG_TILES = new UnicodeBlock("MAHJONG_TILES", - new String[] { "Mahjong Tiles", - "MahjongTiles"}); + "MAHJONG TILES", + "MAHJONGTILES"); /** * Constant for the "Domino Tiles" Unicode character block. @@ -2029,8 +2124,8 @@ */ public static final UnicodeBlock DOMINO_TILES = new UnicodeBlock("DOMINO_TILES", - new String[] { "Domino Tiles", - "DominoTiles"}); + "DOMINO TILES", + "DOMINOTILES"); private static final int blockStarts[] = { 0x0000, // 0000..007F; Basic Latin @@ -2046,7 +2141,7 @@ 0x0530, // 0530..058F; Armenian 0x0590, // 0590..05FF; Hebrew 0x0600, // 0600..06FF; Arabic - 0x0700, // 0700..074F; Syria + 0x0700, // 0700..074F; Syriac 0x0750, // 0750..077F; Arabic Supplement 0x0780, // 0780..07BF; Thaana 0x07C0, // 07C0..07FF; NKo @@ -2446,11 +2541,10 @@ * given character, or <code>null</code> if the character is not a * member of a defined block. * - * <p><b>Note:</b> This method cannot handle <a - * href="Character.html#supplementary"> supplementary - * characters</a>. To support all Unicode characters, - * including supplementary characters, use the {@link - * #of(int)} method. + * <p><b>Note:</b> This method cannot handle + * <a href="Character.html#supplementary"> supplementary + * characters</a>. To support all Unicode characters, including + * supplementary characters, use the {@link #of(int)} method. * * @param c The character in question * @return The <code>UnicodeBlock</code> instance representing the @@ -2462,22 +2556,21 @@ return of((int)c); } - /** * Returns the object representing the Unicode block * containing the given character (Unicode code point), or * <code>null</code> if the character is not a member of a * defined block. * - * @param codePoint the character (Unicode code point) in question. + * @param codePoint the character (Unicode code point) in question. * @return The <code>UnicodeBlock</code> instance representing the * Unicode block of which this character is a member, or * <code>null</code> if the character is not a member of any * Unicode block - * @exception IllegalArgumentException if the specified - * <code>codePoint</code> is an invalid Unicode code point. - * @see Character#isValidCodePoint(int) - * @since 1.5 + * @exception IllegalArgumentException if the specified + * <code>codePoint</code> is an invalid Unicode code point. + * @see Character#isValidCodePoint(int) + * @since 1.5 */ public static UnicodeBlock of(int codePoint) { if (!isValidCodePoint(codePoint)) { @@ -2519,7 +2612,7 @@ * <li>The text representation of each constant UnicodeBlock identifier. * For example, this method will return the {@link #BASIC_LATIN} block if * provided with the "BASIC_LATIN" name. This form replaces all spaces and - * hyphens in the canonical name with underscores. + * hyphens in the canonical name with underscores. * </ol> * Finally, character case is ignored for all of the valid block name forms. * For example, "BASIC_LATIN" and "basic_latin" are both valid block names. @@ -2538,7 +2631,7 @@ * @since 1.5 */ public static final UnicodeBlock forName(String blockName) { - UnicodeBlock block = (UnicodeBlock)map.get(blockName.toUpperCase(Locale.US)); + UnicodeBlock block = map.get(blockName.toUpperCase(Locale.US)); if (block == null) { throw new IllegalArgumentException(); } @@ -3627,7 +3720,7 @@ private static HashMap<String, Character.UnicodeScript> aliases; static { - aliases = new HashMap<String, UnicodeScript>(); + aliases = new HashMap<String, UnicodeScript>(128); aliases.put("ARAB", ARABIC); aliases.put("ARMI", IMPERIAL_ARAMAIC); aliases.put("ARMN", ARMENIAN); @@ -3809,7 +3902,7 @@ static final Character cache[] = new Character[127 + 1]; static { - for(int i = 0; i < cache.length; i++) + for (int i = 0; i < cache.length; i++) cache[i] = new Character((char)i); } } @@ -3832,7 +3925,7 @@ * @since 1.5 */ public static Character valueOf(char c) { - if(c <= 127) { // must cache + if (c <= 127) { // must cache return CharacterCache.cache[(int)c]; } return new Character(c); @@ -3914,7 +4007,29 @@ * @since 1.5 */ public static boolean isValidCodePoint(int codePoint) { - return codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT; + // Optimized form of: + // codePoint >= MIN_CODE_POINT && codePoint <= MAX_CODE_POINT + int plane = codePoint >>> 16; + return plane < ((MAX_CODE_POINT + 1) >>> 16); + } + + /** + * Determines whether the specified character (Unicode code point) + * is in the <a href="#BMP">Basic Multilingual Plane (BMP)</a>. + * Such code points can be represented using a single {@code char}. + * + * @param codePoint the character (Unicode code point) to be tested + * @return {@code true} if the specified code point is between + * {@link #MIN_VALUE} and {@link #MAX_VALUE} inclusive; + * {@code false} otherwise. + * @since 1.7 + */ + public static boolean isBmpCodePoint(int codePoint) { + return codePoint >>> 16 == 0; + // Optimized form of: + // codePoint >= MIN_VALUE && codePoint <= MAX_VALUE + // We consistently use logical shift (>>>) to facilitate + // additional runtime optimizations. } /** @@ -3930,7 +4045,7 @@ */ public static boolean isSupplementaryCodePoint(int codePoint) { return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT - && codePoint <= MAX_CODE_POINT; + && codePoint < MAX_CODE_POINT + 1; } /** @@ -3949,12 +4064,13 @@ * {@link #MIN_HIGH_SURROGATE} and * {@link #MAX_HIGH_SURROGATE} inclusive; * {@code false} otherwise. - * @see #isLowSurrogate(char) + * @see Character#isLowSurrogate(char) * @see Character.UnicodeBlock#of(int) * @since 1.5 */ public static boolean isHighSurrogate(char ch) { - return ch >= MIN_HIGH_SURROGATE && ch <= MAX_HIGH_SURROGATE; + // Help VM constant-fold; MAX_HIGH_SURROGATE + 1 == MIN_LOW_SURROGATE + return ch >= MIN_HIGH_SURROGATE && ch < (MAX_HIGH_SURROGATE + 1); } /** @@ -3973,11 +4089,11 @@ * {@link #MIN_LOW_SURROGATE} and * {@link #MAX_LOW_SURROGATE} inclusive; * {@code false} otherwise. - * @see #isHighSurrogate(char) + * @see Character#isHighSurrogate(char) * @since 1.5 */ public static boolean isLowSurrogate(char ch) { - return ch >= MIN_LOW_SURROGATE && ch <= MAX_LOW_SURROGATE; + return ch >= MIN_LOW_SURROGATE && ch < (MAX_LOW_SURROGATE + 1); } /** @@ -4001,7 +4117,7 @@ * @since 1.7 */ public static boolean isSurrogate(char ch) { - return ch >= MIN_SURROGATE && ch <= MAX_SURROGATE; + return ch >= MIN_SURROGATE && ch < (MAX_SURROGATE + 1); } /** @@ -4039,11 +4155,11 @@ * * @param codePoint the character (Unicode code point) to be tested. * @return 2 if the character is a valid supplementary character; 1 otherwise. - * @see #isSupplementaryCodePoint(int) + * @see Character#isSupplementaryCodePoint(int) * @since 1.5 */ public static int charCount(int codePoint) { - return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT? 2 : 1; + return codePoint >= MIN_SUPPLEMENTARY_CODE_POINT ? 2 : 1; } /** @@ -4160,6 +4276,7 @@ return codePointAtImpl(a, index, limit); } + // throws ArrayIndexOutofBoundsException if index out of bounds static int codePointAtImpl(char[] a, int index, int limit) { char c1 = a[index++]; if (isHighSurrogate(c1)) { @@ -4266,6 +4383,7 @@ return codePointBeforeImpl(a, index, start); } + // throws ArrayIndexOutofBoundsException if index-1 out of bounds static int codePointBeforeImpl(char[] a, int index, int start) { char c2 = a[--index]; if (isLowSurrogate(c2)) { @@ -4280,6 +4398,63 @@ } /** + * Returns the leading surrogate (a + * <a href="http://www.unicode.org/glossary/#high_surrogate_code_unit"> + * high surrogate code unit</a>) of the + * <a href="http://www.unicode.org/glossary/#surrogate_pair"> + * surrogate pair</a> + * representing the specified supplementary character (Unicode + * code point) in the UTF-16 encoding. If the specified character + * is not a + * <a href="Character.html#supplementary">supplementary character</a>, + * an unspecified {@code char} is returned. + * + * <p>If + * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)} + * is {@code true}, then + * {@link #isHighSurrogate isHighSurrogate}{@code (highSurrogate(x))} and + * {@link #toCodePoint toCodePoint}{@code (highSurrogate(x), }{@link #lowSurrogate lowSurrogate}{@code (x)) == x} + * are also always {@code true}. + * + * @param codePoint a supplementary character (Unicode code point) + * @return the leading surrogate code unit used to represent the + * character in the UTF-16 encoding + * @since 1.7 + */ + public static char highSurrogate(int codePoint) { + return (char) ((codePoint >>> 10) + + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10))); + } + + /** + * Returns the trailing surrogate (a + * <a href="http://www.unicode.org/glossary/#low_surrogate_code_unit"> + * low surrogate code unit</a>) of the + * <a href="http://www.unicode.org/glossary/#surrogate_pair"> + * surrogate pair</a> + * representing the specified supplementary character (Unicode + * code point) in the UTF-16 encoding. If the specified character + * is not a + * <a href="Character.html#supplementary">supplementary character</a>, + * an unspecified {@code char} is returned. + * + * <p>If + * {@link #isSupplementaryCodePoint isSupplementaryCodePoint(x)} + * is {@code true}, then + * {@link #isLowSurrogate isLowSurrogate}{@code (lowSurrogate(x))} and + * {@link #toCodePoint toCodePoint}{@code (}{@link #highSurrogate highSurrogate}{@code (x), lowSurrogate(x)) == x} + * are also always {@code true}. + * + * @param codePoint a supplementary character (Unicode code point) + * @return the trailing surrogate code unit used to represent the + * character in the UTF-16 encoding + * @since 1.7 + */ + public static char lowSurrogate(int codePoint) { + return (char) ((codePoint & 0x3ff) + MIN_LOW_SURROGATE); + } + + /** * Converts the specified character (Unicode code point) to its * UTF-16 representation. If the specified code point is a BMP * (Basic Multilingual Plane or Plane 0) value, the same value is @@ -4311,15 +4486,15 @@ * @since 1.5 */ public static int toChars(int codePoint, char[] dst, int dstIndex) { - if (codePoint < 0 || codePoint > MAX_CODE_POINT) { + if (isBmpCodePoint(codePoint)) { + dst[dstIndex] = (char) codePoint; + return 1; + } else if (isValidCodePoint(codePoint)) { + toSurrogates(codePoint, dst, dstIndex); + return 2; + } else { throw new IllegalArgumentException(); } - if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { - dst[dstIndex] = (char) codePoint; - return 1; - } - toSurrogates(codePoint, dst, dstIndex); - return 2; } /** @@ -4339,22 +4514,21 @@ * @since 1.5 */ public static char[] toChars(int codePoint) { - if (codePoint < 0 || codePoint > MAX_CODE_POINT) { + if (isBmpCodePoint(codePoint)) { + return new char[] { (char) codePoint }; + } else if (isValidCodePoint(codePoint)) { + char[] result = new char[2]; + toSurrogates(codePoint, result, 0); + return result; + } else { throw new IllegalArgumentException(); } - if (codePoint < MIN_SUPPLEMENTARY_CODE_POINT) { - return new char[] { (char) codePoint }; - } - char[] result = new char[2]; - toSurrogates(codePoint, result, 0); - return result; } static void toSurrogates(int codePoint, char[] dst, int index) { // We write elements "backwards" to guarantee all-or-nothing - dst[index+1] = (char)((codePoint & 0x3ff) + MIN_LOW_SURROGATE); - dst[index] = (char)((codePoint >>> 10) - + (MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10))); + dst[index+1] = lowSurrogate(codePoint); + dst[index] = highSurrogate(codePoint); } /** @@ -4385,13 +4559,12 @@ if (beginIndex < 0 || endIndex > length || beginIndex > endIndex) { throw new IndexOutOfBoundsException(); } - int n = 0; + int n = endIndex - beginIndex; for (int i = beginIndex; i < endIndex; ) { - n++; - if (isHighSurrogate(seq.charAt(i++))) { - if (i < endIndex && isLowSurrogate(seq.charAt(i))) { - i++; - } + if (isHighSurrogate(seq.charAt(i++)) && i < endIndex && + isLowSurrogate(seq.charAt(i))) { + n--; + i++; } } return n; @@ -4425,13 +4598,12 @@ static int codePointCountImpl(char[] a, int offset, int count) { int endIndex = offset + count; - int n = 0; + int n = count; for (int i = offset; i < endIndex; ) { - n++; - if (isHighSurrogate(a[i++])) { - if (i < endIndex && isLowSurrogate(a[i])) { - i++; - } + if (isHighSurrogate(a[i++]) && i < endIndex && + isLowSurrogate(a[i])) { + n--; + i++; } } return n; @@ -4470,10 +4642,9 @@ if (codePointOffset >= 0) { int i; for (i = 0; x < length && i < codePointOffset; i++) { - if (isHighSurrogate(seq.charAt(x++))) { - if (x < length && isLowSurrogate(seq.charAt(x))) { - x++; - } + if (isHighSurrogate(seq.charAt(x++)) && x < length && + isLowSurrogate(seq.charAt(x))) { + x++; } } if (i < codePointOffset) { @@ -4482,10 +4653,9 @@ } else { int i; for (i = codePointOffset; x > 0 && i < 0; i++) { - if (isLowSurrogate(seq.charAt(--x))) { - if (x > 0 && isHighSurrogate(seq.charAt(x-1))) { - x--; - } + if (isLowSurrogate(seq.charAt(--x)) && x > 0 && + isHighSurrogate(seq.charAt(x-1))) { + x--; } } if (i < 0) { @@ -4544,10 +4714,9 @@ int limit = start + count; int i; for (i = 0; x < limit && i < codePointOffset; i++) { - if (isHighSurrogate(a[x++])) { - if (x < limit && isLowSurrogate(a[x])) { - x++; - } + if (isHighSurrogate(a[x++]) && x < limit && + isLowSurrogate(a[x])) { + x++; } } if (i < codePointOffset) { @@ -4556,10 +4725,9 @@ } else { int i; for (i = codePointOffset; x > start && i < 0; i++) { - if (isLowSurrogate(a[--x])) { - if (x > start && isHighSurrogate(a[x-1])) { - x--; - } + if (isLowSurrogate(a[--x]) && x > start && + isHighSurrogate(a[x-1])) { + x--; } } if (i < 0) { @@ -4569,7 +4737,7 @@ return x; } - /** + /** * Determines if the specified character is a lowercase character. * <p> * A character is lowercase if its general category type, provided @@ -4594,10 +4762,10 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is lowercase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isTitleCase(char) - * @see java.lang.Character#toLowerCase(char) - * @see java.lang.Character#getType(char) + * @see Character#isLowerCase(char) + * @see Character#isTitleCase(char) + * @see Character#toLowerCase(char) + * @see Character#getType(char) */ public static boolean isLowerCase(char ch) { return isLowerCase((int)ch); @@ -4624,17 +4792,17 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is lowercase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.Character#isTitleCase(int) - * @see java.lang.Character#toLowerCase(int) - * @see java.lang.Character#getType(int) + * @see Character#isLowerCase(int) + * @see Character#isTitleCase(int) + * @see Character#toLowerCase(int) + * @see Character#getType(int) * @since 1.5 */ public static boolean isLowerCase(int codePoint) { return getType(codePoint) == Character.LOWERCASE_LETTER; } - /** + /** * Determines if the specified character is an uppercase character. * <p> * A character is uppercase if its general category type, provided by @@ -4658,10 +4826,10 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is uppercase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isTitleCase(char) - * @see java.lang.Character#toUpperCase(char) - * @see java.lang.Character#getType(char) + * @see Character#isLowerCase(char) + * @see Character#isTitleCase(char) + * @see Character#toUpperCase(char) + * @see Character#getType(char) * @since 1.0 */ public static boolean isUpperCase(char ch) { @@ -4687,10 +4855,10 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is uppercase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.Character#isTitleCase(int) - * @see java.lang.Character#toUpperCase(int) - * @see java.lang.Character#getType(int) + * @see Character#isLowerCase(int) + * @see Character#isTitleCase(int) + * @see Character#toUpperCase(int) + * @see Character#getType(int) * @since 1.5 */ public static boolean isUpperCase(int codePoint) { @@ -4728,10 +4896,10 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is titlecase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isUpperCase(char) - * @see java.lang.Character#toTitleCase(char) - * @see java.lang.Character#getType(char) + * @see Character#isLowerCase(char) + * @see Character#isUpperCase(char) + * @see Character#toTitleCase(char) + * @see Character#getType(char) * @since 1.0.2 */ public static boolean isTitleCase(char ch) { @@ -4764,10 +4932,10 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is titlecase; * <code>false</code> otherwise. - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.Character#isUpperCase(int) - * @see java.lang.Character#toTitleCase(int) - * @see java.lang.Character#getType(int) + * @see Character#isLowerCase(int) + * @see Character#isUpperCase(int) + * @see Character#toTitleCase(int) + * @see Character#getType(int) * @since 1.5 */ public static boolean isTitleCase(int codePoint) { @@ -4805,9 +4973,9 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is a digit; * <code>false</code> otherwise. - * @see java.lang.Character#digit(char, int) - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#getType(char) + * @see Character#digit(char, int) + * @see Character#forDigit(int, int) + * @see Character#getType(char) */ public static boolean isDigit(char ch) { return isDigit((int)ch); @@ -4839,8 +5007,8 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is a digit; * <code>false</code> otherwise. - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#getType(int) + * @see Character#forDigit(int, int) + * @see Character#getType(int) * @since 1.5 */ public static boolean isDigit(int codePoint) { @@ -4864,12 +5032,12 @@ * @param ch the character to be tested * @return <code>true</code> if the character has a defined meaning * in Unicode; <code>false</code> otherwise. - * @see java.lang.Character#isDigit(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isTitleCase(char) - * @see java.lang.Character#isUpperCase(char) + * @see Character#isDigit(char) + * @see Character#isLetter(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isLowerCase(char) + * @see Character#isTitleCase(char) + * @see Character#isUpperCase(char) * @since 1.0.2 */ public static boolean isDefined(char ch) { @@ -4888,12 +5056,12 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character has a defined meaning * in Unicode; <code>false</code> otherwise. - * @see java.lang.Character#isDigit(int) - * @see java.lang.Character#isLetter(int) - * @see java.lang.Character#isLetterOrDigit(int) - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.Character#isTitleCase(int) - * @see java.lang.Character#isUpperCase(int) + * @see Character#isDigit(int) + * @see Character#isLetter(int) + * @see Character#isLetterOrDigit(int) + * @see Character#isLowerCase(int) + * @see Character#isTitleCase(int) + * @see Character#isUpperCase(int) * @since 1.5 */ public static boolean isDefined(int codePoint) { @@ -4925,15 +5093,15 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is a letter; * <code>false</code> otherwise. - * @see java.lang.Character#isDigit(char) - * @see java.lang.Character#isJavaIdentifierStart(char) - * @see java.lang.Character#isJavaLetter(char) - * @see java.lang.Character#isJavaLetterOrDigit(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isTitleCase(char) - * @see java.lang.Character#isUnicodeIdentifierStart(char) - * @see java.lang.Character#isUpperCase(char) + * @see Character#isDigit(char) + * @see Character#isJavaIdentifierStart(char) + * @see Character#isJavaLetter(char) + * @see Character#isJavaLetterOrDigit(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isLowerCase(char) + * @see Character#isTitleCase(char) + * @see Character#isUnicodeIdentifierStart(char) + * @see Character#isUpperCase(char) */ public static boolean isLetter(char ch) { return isLetter((int)ch); @@ -4959,13 +5127,13 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is a letter; * <code>false</code> otherwise. - * @see java.lang.Character#isDigit(int) - * @see java.lang.Character#isJavaIdentifierStart(int) - * @see java.lang.Character#isLetterOrDigit(int) - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.Character#isTitleCase(int) - * @see java.lang.Character#isUnicodeIdentifierStart(int) - * @see java.lang.Character#isUpperCase(int) + * @see Character#isDigit(int) + * @see Character#isJavaIdentifierStart(int) + * @see Character#isLetterOrDigit(int) + * @see Character#isLowerCase(int) + * @see Character#isTitleCase(int) + * @see Character#isUnicodeIdentifierStart(int) + * @see Character#isUpperCase(int) * @since 1.5 */ public static boolean isLetter(int codePoint) { @@ -4993,12 +5161,12 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is a letter or digit; * <code>false</code> otherwise. - * @see java.lang.Character#isDigit(char) - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isJavaLetter(char) - * @see java.lang.Character#isJavaLetterOrDigit(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isUnicodeIdentifierPart(char) + * @see Character#isDigit(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isJavaLetter(char) + * @see Character#isJavaLetterOrDigit(char) + * @see Character#isLetter(char) + * @see Character#isUnicodeIdentifierPart(char) * @since 1.0.2 */ public static boolean isLetterOrDigit(char ch) { @@ -5016,10 +5184,10 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is a letter or digit; * <code>false</code> otherwise. - * @see java.lang.Character#isDigit(int) - * @see java.lang.Character#isJavaIdentifierPart(int) - * @see java.lang.Character#isLetter(int) - * @see java.lang.Character#isUnicodeIdentifierPart(int) + * @see Character#isDigit(int) + * @see Character#isJavaIdentifierPart(int) + * @see Character#isLetter(int) + * @see Character#isUnicodeIdentifierPart(int) * @since 1.5 */ public static boolean isLetterOrDigit(int codePoint) { @@ -5048,12 +5216,12 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may start a Java * identifier; <code>false</code> otherwise. - * @see java.lang.Character#isJavaLetterOrDigit(char) - * @see java.lang.Character#isJavaIdentifierStart(char) - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isUnicodeIdentifierStart(char) + * @see Character#isJavaLetterOrDigit(char) + * @see Character#isJavaIdentifierStart(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isLetter(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isUnicodeIdentifierStart(char) * @since 1.02 * @deprecated Replaced by isJavaIdentifierStart(char). */ @@ -5083,13 +5251,13 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may be part of a * Java identifier; <code>false</code> otherwise. - * @see java.lang.Character#isJavaLetter(char) - * @see java.lang.Character#isJavaIdentifierStart(char) - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isUnicodeIdentifierPart(char) - * @see java.lang.Character#isIdentifierIgnorable(char) + * @see Character#isJavaLetter(char) + * @see Character#isJavaIdentifierStart(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isLetter(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isUnicodeIdentifierPart(char) + * @see Character#isIdentifierIgnorable(char) * @since 1.02 * @deprecated Replaced by isJavaIdentifierPart(char). */ @@ -5119,9 +5287,9 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may start a Java identifier; * <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isUnicodeIdentifierStart(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isLetter(char) + * @see Character#isUnicodeIdentifierStart(char) * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ @@ -5148,9 +5316,9 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character may start a Java identifier; * <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierPart(int) - * @see java.lang.Character#isLetter(int) - * @see java.lang.Character#isUnicodeIdentifierStart(int) + * @see Character#isJavaIdentifierPart(int) + * @see Character#isLetter(int) + * @see Character#isUnicodeIdentifierStart(int) * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ @@ -5184,10 +5352,10 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may be part of a * Java identifier; <code>false</code> otherwise. - * @see java.lang.Character#isIdentifierIgnorable(char) - * @see java.lang.Character#isJavaIdentifierStart(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isUnicodeIdentifierPart(char) + * @see Character#isIdentifierIgnorable(char) + * @see Character#isJavaIdentifierStart(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isUnicodeIdentifierPart(char) * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.1 */ @@ -5217,10 +5385,10 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character may be part of a * Java identifier; <code>false</code> otherwise. - * @see java.lang.Character#isIdentifierIgnorable(int) - * @see java.lang.Character#isJavaIdentifierStart(int) - * @see java.lang.Character#isLetterOrDigit(int) - * @see java.lang.Character#isUnicodeIdentifierPart(int) + * @see Character#isIdentifierIgnorable(int) + * @see Character#isJavaIdentifierStart(int) + * @see Character#isLetterOrDigit(int) + * @see Character#isUnicodeIdentifierPart(int) * @see javax.lang.model.SourceVersion#isIdentifier(CharSequence) * @since 1.5 */ @@ -5248,9 +5416,9 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may start a Unicode * identifier; <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierStart(char) - * @see java.lang.Character#isLetter(char) - * @see java.lang.Character#isUnicodeIdentifierPart(char) + * @see Character#isJavaIdentifierStart(char) + * @see Character#isLetter(char) + * @see Character#isUnicodeIdentifierPart(char) * @since 1.1 */ public static boolean isUnicodeIdentifierStart(char ch) { @@ -5272,9 +5440,9 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character may start a Unicode * identifier; <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierStart(int) - * @see java.lang.Character#isLetter(int) - * @see java.lang.Character#isUnicodeIdentifierPart(int) + * @see Character#isJavaIdentifierStart(int) + * @see Character#isLetter(int) + * @see Character#isUnicodeIdentifierPart(int) * @since 1.5 */ public static boolean isUnicodeIdentifierStart(int codePoint) { @@ -5306,10 +5474,10 @@ * @param ch the character to be tested. * @return <code>true</code> if the character may be part of a * Unicode identifier; <code>false</code> otherwise. - * @see java.lang.Character#isIdentifierIgnorable(char) - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isLetterOrDigit(char) - * @see java.lang.Character#isUnicodeIdentifierStart(char) + * @see Character#isIdentifierIgnorable(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isLetterOrDigit(char) + * @see Character#isUnicodeIdentifierStart(char) * @since 1.1 */ public static boolean isUnicodeIdentifierPart(char ch) { @@ -5335,10 +5503,10 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character may be part of a * Unicode identifier; <code>false</code> otherwise. - * @see java.lang.Character#isIdentifierIgnorable(int) - * @see java.lang.Character#isJavaIdentifierPart(int) - * @see java.lang.Character#isLetterOrDigit(int) - * @see java.lang.Character#isUnicodeIdentifierStart(int) + * @see Character#isIdentifierIgnorable(int) + * @see Character#isJavaIdentifierPart(int) + * @see Character#isLetterOrDigit(int) + * @see Character#isUnicodeIdentifierStart(int) * @since 1.5 */ public static boolean isUnicodeIdentifierPart(int codePoint) { @@ -5372,8 +5540,8 @@ * @return <code>true</code> if the character is an ignorable control * character that may be part of a Java or Unicode identifier; * <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierPart(char) - * @see java.lang.Character#isUnicodeIdentifierPart(char) + * @see Character#isJavaIdentifierPart(char) + * @see Character#isUnicodeIdentifierPart(char) * @since 1.1 */ public static boolean isIdentifierIgnorable(char ch) { @@ -5402,8 +5570,8 @@ * @return <code>true</code> if the character is an ignorable control * character that may be part of a Java or Unicode identifier; * <code>false</code> otherwise. - * @see java.lang.Character#isJavaIdentifierPart(int) - * @see java.lang.Character#isUnicodeIdentifierPart(int) + * @see Character#isJavaIdentifierPart(int) + * @see Character#isUnicodeIdentifierPart(int) * @since 1.5 */ public static boolean isIdentifierIgnorable(int codePoint) { @@ -5419,7 +5587,7 @@ * does not always return <code>true</code> for some ranges of * characters, particularly those that are symbols or ideographs. * - * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map + * <p>In general, {@link String#toLowerCase()} should be used to map * characters to lowercase. <code>String</code> case mapping methods * have several benefits over <code>Character</code> case mapping methods. * <code>String</code> case mapping methods can perform locale-sensitive @@ -5434,8 +5602,8 @@ * @param ch the character to be converted. * @return the lowercase equivalent of the character, if any; * otherwise, the character itself. - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.String#toLowerCase() + * @see Character#isLowerCase(char) + * @see String#toLowerCase() */ public static char toLowerCase(char ch) { return (char)toLowerCase((int)ch); @@ -5451,7 +5619,7 @@ * does not always return <code>true</code> for some ranges of * characters, particularly those that are symbols or ideographs. * - * <p>In general, {@link java.lang.String#toLowerCase()} should be used to map + * <p>In general, {@link String#toLowerCase()} should be used to map * characters to lowercase. <code>String</code> case mapping methods * have several benefits over <code>Character</code> case mapping methods. * <code>String</code> case mapping methods can perform locale-sensitive @@ -5461,8 +5629,8 @@ * @param codePoint the character (Unicode code point) to be converted. * @return the lowercase equivalent of the character (Unicode code * point), if any; otherwise, the character itself. - * @see java.lang.Character#isLowerCase(int) - * @see java.lang.String#toLowerCase() + * @see Character#isLowerCase(int) + * @see String#toLowerCase() * * @since 1.5 */ @@ -5479,7 +5647,7 @@ * does not always return <code>true</code> for some ranges of * characters, particularly those that are symbols or ideographs. * - * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map + * <p>In general, {@link String#toUpperCase()} should be used to map * characters to uppercase. <code>String</code> case mapping methods * have several benefits over <code>Character</code> case mapping methods. * <code>String</code> case mapping methods can perform locale-sensitive @@ -5494,8 +5662,8 @@ * @param ch the character to be converted. * @return the uppercase equivalent of the character, if any; * otherwise, the character itself. - * @see java.lang.Character#isUpperCase(char) - * @see java.lang.String#toUpperCase() + * @see Character#isUpperCase(char) + * @see String#toUpperCase() */ public static char toUpperCase(char ch) { return (char)toUpperCase((int)ch); @@ -5511,7 +5679,7 @@ * does not always return <code>true</code> for some ranges of * characters, particularly those that are symbols or ideographs. * - * <p>In general, {@link java.lang.String#toUpperCase()} should be used to map + * <p>In general, {@link String#toUpperCase()} should be used to map * characters to uppercase. <code>String</code> case mapping methods * have several benefits over <code>Character</code> case mapping methods. * <code>String</code> case mapping methods can perform locale-sensitive @@ -5521,8 +5689,8 @@ * @param codePoint the character (Unicode code point) to be converted. * @return the uppercase equivalent of the character, if any; * otherwise, the character itself. - * @see java.lang.Character#isUpperCase(int) - * @see java.lang.String#toUpperCase() + * @see Character#isUpperCase(int) + * @see String#toUpperCase() * * @since 1.5 */ @@ -5553,9 +5721,9 @@ * @param ch the character to be converted. * @return the titlecase equivalent of the character, if any; * otherwise, the character itself. - * @see java.lang.Character#isTitleCase(char) - * @see java.lang.Character#toLowerCase(char) - * @see java.lang.Character#toUpperCase(char) + * @see Character#isTitleCase(char) + * @see Character#toLowerCase(char) + * @see Character#toUpperCase(char) * @since 1.0.2 */ public static char toTitleCase(char ch) { @@ -5580,9 +5748,9 @@ * @param codePoint the character (Unicode code point) to be converted. * @return the titlecase equivalent of the character, if any; * otherwise, the character itself. - * @see java.lang.Character#isTitleCase(int) - * @see java.lang.Character#toLowerCase(int) - * @see java.lang.Character#toUpperCase(int) + * @see Character#isTitleCase(int) + * @see Character#toLowerCase(int) + * @see Character#toUpperCase(int) * @since 1.5 */ public static int toTitleCase(int codePoint) { @@ -5624,8 +5792,8 @@ * @param radix the radix. * @return the numeric value represented by the character in the * specified radix. - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#isDigit(char) + * @see Character#forDigit(int, int) + * @see Character#isDigit(char) */ public static int digit(char ch, int radix) { return digit((int)ch, radix); @@ -5661,8 +5829,8 @@ * @param radix the radix. * @return the numeric value represented by the character in the * specified radix. - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#isDigit(int) + * @see Character#forDigit(int, int) + * @see Character#isDigit(int) * @since 1.5 */ public static int digit(int codePoint, int radix) { @@ -5699,8 +5867,8 @@ * @return the numeric value of the character, as a nonnegative <code>int</code> * value; -2 if the character has a numeric value that is not a * nonnegative integer; -1 if the character has no numeric value. - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#isDigit(char) + * @see Character#forDigit(int, int) + * @see Character#isDigit(char) * @since 1.1 */ public static int getNumericValue(char ch) { @@ -5732,8 +5900,8 @@ * @return the numeric value of the character, as a nonnegative <code>int</code> * value; -2 if the character has a numeric value that is not a * nonnegative integer; -1 if the character has no numeric value. - * @see java.lang.Character#forDigit(int, int) - * @see java.lang.Character#isDigit(int) + * @see Character#forDigit(int, int) + * @see Character#isDigit(int) * @since 1.5 */ public static int getNumericValue(int codePoint) { @@ -5760,8 +5928,8 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is ISO-LATIN-1 white * space; <code>false</code> otherwise. - * @see java.lang.Character#isSpaceChar(char) - * @see java.lang.Character#isWhitespace(char) + * @see Character#isSpaceChar(char) + * @see Character#isWhitespace(char) * @deprecated Replaced by isWhitespace(char). */ @Deprecated @@ -5795,7 +5963,7 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is a space character; * <code>false</code> otherwise. - * @see java.lang.Character#isWhitespace(char) + * @see Character#isWhitespace(char) * @since 1.1 */ public static boolean isSpaceChar(char ch) { @@ -5818,7 +5986,7 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is a space character; * <code>false</code> otherwise. - * @see java.lang.Character#isWhitespace(int) + * @see Character#isWhitespace(int) * @since 1.5 */ public static boolean isSpaceChar(int codePoint) { @@ -5856,7 +6024,7 @@ * @param ch the character to be tested. * @return <code>true</code> if the character is a Java whitespace * character; <code>false</code> otherwise. - * @see java.lang.Character#isSpaceChar(char) + * @see Character#isSpaceChar(char) * @since 1.1 */ public static boolean isWhitespace(char ch) { @@ -5888,7 +6056,7 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is a Java whitespace * character; <code>false</code> otherwise. - * @see java.lang.Character#isSpaceChar(int) + * @see Character#isSpaceChar(int) * @since 1.5 */ public static boolean isWhitespace(int codePoint) { @@ -5911,8 +6079,8 @@ * @return <code>true</code> if the character is an ISO control character; * <code>false</code> otherwise. * - * @see java.lang.Character#isSpaceChar(char) - * @see java.lang.Character#isWhitespace(char) + * @see Character#isSpaceChar(char) + * @see Character#isWhitespace(char) * @since 1.1 */ public static boolean isISOControl(char ch) { @@ -5929,13 +6097,16 @@ * @param codePoint the character (Unicode code point) to be tested. * @return <code>true</code> if the character is an ISO control character; * <code>false</code> otherwise. - * @see java.lang.Character#isSpaceChar(int) - * @see java.lang.Character#isWhitespace(int) + * @see Character#isSpaceChar(int) + * @see Character#isWhitespace(int) * @since 1.5 */ public static boolean isISOControl(int codePoint) { - return (codePoint >= 0x0000 && codePoint <= 0x001F) || - (codePoint >= 0x007F && codePoint <= 0x009F); + // Optimized form of: + // (codePoint >= 0x00 && codePoint <= 0x1F) || + // (codePoint >= 0x7F && codePoint <= 0x9F); + return codePoint <= 0x9F && + (codePoint >= 0x7F || (codePoint >>> 5 == 0)); } /** @@ -5949,36 +6120,36 @@ * @param ch the character to be tested. * @return a value of type <code>int</code> representing the * character's general category. - * @see java.lang.Character#COMBINING_SPACING_MARK - * @see java.lang.Character#CONNECTOR_PUNCTUATION - * @see java.lang.Character#CONTROL - * @see java.lang.Character#CURRENCY_SYMBOL - * @see java.lang.Character#DASH_PUNCTUATION - * @see java.lang.Character#DECIMAL_DIGIT_NUMBER - * @see java.lang.Character#ENCLOSING_MARK - * @see java.lang.Character#END_PUNCTUATION - * @see java.lang.Character#FINAL_QUOTE_PUNCTUATION - * @see java.lang.Character#FORMAT - * @see java.lang.Character#INITIAL_QUOTE_PUNCTUATION - * @see java.lang.Character#LETTER_NUMBER - * @see java.lang.Character#LINE_SEPARATOR - * @see java.lang.Character#LOWERCASE_LETTER - * @see java.lang.Character#MATH_SYMBOL - * @see java.lang.Character#MODIFIER_LETTER - * @see java.lang.Character#MODIFIER_SYMBOL - * @see java.lang.Character#NON_SPACING_MARK - * @see java.lang.Character#OTHER_LETTER - * @see java.lang.Character#OTHER_NUMBER - * @see java.lang.Character#OTHER_PUNCTUATION - * @see java.lang.Character#OTHER_SYMBOL - * @see java.lang.Character#PARAGRAPH_SEPARATOR - * @see java.lang.Character#PRIVATE_USE - * @see java.lang.Character#SPACE_SEPARATOR - * @see java.lang.Character#START_PUNCTUATION - * @see java.lang.Character#SURROGATE - * @see java.lang.Character#TITLECASE_LETTER - * @see java.lang.Character#UNASSIGNED - * @see java.lang.Character#UPPERCASE_LETTER + * @see Character#COMBINING_SPACING_MARK + * @see Character#CONNECTOR_PUNCTUATION + * @see Character#CONTROL + * @see Character#CURRENCY_SYMBOL + * @see Character#DASH_PUNCTUATION + * @see Character#DECIMAL_DIGIT_NUMBER + * @see Character#ENCLOSING_MARK + * @see Character#END_PUNCTUATION + * @see Character#FINAL_QUOTE_PUNCTUATION + * @see Character#FORMAT + * @see Character#INITIAL_QUOTE_PUNCTUATION + * @see Character#LETTER_NUMBER + * @see Character#LINE_SEPARATOR + * @see Character#LOWERCASE_LETTER + * @see Character#MATH_SYMBOL + * @see Character#MODIFIER_LETTER + * @see Character#MODIFIER_SYMBOL + * @see Character#NON_SPACING_MARK + * @see Character#OTHER_LETTER + * @see Character#OTHER_NUMBER + * @see Character#OTHER_PUNCTUATION + * @see Character#OTHER_SYMBOL + * @see Character#PARAGRAPH_SEPARATOR + * @see Character#PRIVATE_USE + * @see Character#SPACE_SEPARATOR + * @see Character#START_PUNCTUATION + * @see Character#SURROGATE + * @see Character#TITLECASE_LETTER + * @see Character#UNASSIGNED + * @see Character#UPPERCASE_LETTER * @since 1.1 */ public static int getType(char ch) { @@ -6047,9 +6218,9 @@ * @param radix the radix. * @return the <code>char</code> representation of the specified digit * in the specified radix. - * @see java.lang.Character#MIN_RADIX - * @see java.lang.Character#MAX_RADIX - * @see java.lang.Character#digit(char, int) + * @see Character#MIN_RADIX + * @see Character#MAX_RADIX + * @see Character#digit(char, int) */ public static char forDigit(int digit, int radix) { if ((digit >= radix) || (digit < 0)) { @@ -6230,10 +6401,10 @@ * @return either the uppercase equivalent of the character, if * any, or an error flag (<code>Character.ERROR</code>) * that indicates that a 1:M <code>char</code> mapping exists. - * @see java.lang.Character#isLowerCase(char) - * @see java.lang.Character#isUpperCase(char) - * @see java.lang.Character#toLowerCase(char) - * @see java.lang.Character#toTitleCase(char) + * @see Character#isLowerCase(char) + * @see Character#isUpperCase(char) + * @see Character#toLowerCase(char) + * @see Character#toTitleCase(char) * @since 1.4 */ static int toUpperCaseEx(int codePoint) { @@ -6254,8 +6425,7 @@ */ static char[] toUpperCaseCharArray(int codePoint) { // As of Unicode 4.0, 1:M uppercasings only happen in the BMP. - assert isValidCodePoint(codePoint) && - !isSupplementaryCodePoint(codePoint); + assert isBmpCodePoint(codePoint); return CharacterData.of(codePoint).toUpperCaseCharArray(codePoint); }
--- a/src/share/classes/java/lang/String.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/lang/String.java Tue Jul 20 22:21:31 2010 -0700 @@ -38,7 +38,6 @@ import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; - /** * The <code>String</code> class represents character strings. All * string literals in Java programs, such as <code>"abc"</code>, are @@ -99,6 +98,8 @@ * * @author Lee Boynton * @author Arthur van Hoff + * @author Martin Buchholz + * @author Ulf Zibis * @see java.lang.Object#toString() * @see java.lang.StringBuffer * @see java.lang.StringBuilder @@ -273,32 +274,32 @@ throw new StringIndexOutOfBoundsException(offset + count); } + final int end = offset + count; + // Pass 1: Compute precise size of char[] - int n = 0; - for (int i = offset; i < offset + count; i++) { + int n = count; + for (int i = offset; i < end; i++) { int c = codePoints[i]; - if (c >= Character.MIN_CODE_POINT && - c < Character.MIN_SUPPLEMENTARY_CODE_POINT) - n += 1; - else if (Character.isSupplementaryCodePoint(c)) - n += 2; + if (Character.isBmpCodePoint(c)) + continue; + else if (Character.isValidCodePoint(c)) + n++; else throw new IllegalArgumentException(Integer.toString(c)); } // Pass 2: Allocate and fill in char[] - char[] v = new char[n]; - for (int i = offset, j = 0; i < offset + count; i++) { + final char[] v = new char[n]; + + for (int i = offset, j = 0; i < end; i++, j++) { int c = codePoints[i]; - if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) { - v[j++] = (char) c; - } else { - Character.toSurrogates(c, v, j); - j += 2; - } + if (Character.isBmpCodePoint(c)) + v[j] = (char) c; + else + Character.toSurrogates(c, v, j++); } this.value = v; - this.count = v.length; + this.count = n; this.offset = 0; } @@ -1573,9 +1574,6 @@ * if the character does not occur. */ public int indexOf(int ch, int fromIndex) { - int max = offset + count; - char v[] = value; - if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= count) { @@ -1583,29 +1581,36 @@ return -1; } - int i = offset + fromIndex; if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) - for (; i < max ; i++) { - if (v[i] == ch) { + final char[] value = this.value; + final int offset = this.offset; + final int max = offset + count; + for (int i = offset + fromIndex; i < max ; i++) { + if (value[i] == ch) { return i - offset; } } return -1; + } else { + return indexOfSupplementary(ch, fromIndex); } + } - if (ch <= Character.MAX_CODE_POINT) { - // handle supplementary characters here - char[] surrogates = Character.toChars(ch); - for (; i < max; i++) { - if (v[i] == surrogates[0]) { - if (i + 1 == max) { - break; - } - if (v[i+1] == surrogates[1]) { - return i - offset; - } + /** + * Handles (rare) calls of indexOf with a supplementary character. + */ + private int indexOfSupplementary(int ch, int fromIndex) { + if (Character.isValidCodePoint(ch)) { + final char[] value = this.value; + final int offset = this.offset; + final char hi = Character.highSurrogate(ch); + final char lo = Character.lowSurrogate(ch); + final int max = offset + count - 1; + for (int i = offset + fromIndex; i < max; i++) { + if (value[i] == hi && value[i+1] == lo) { + return i - offset; } } } @@ -1674,34 +1679,36 @@ * if the character does not occur before that point. */ public int lastIndexOf(int ch, int fromIndex) { - int min = offset; - char v[] = value; - - int i = offset + ((fromIndex >= count) ? count - 1 : fromIndex); - if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) - for (; i >= min ; i--) { - if (v[i] == ch) { + final char[] value = this.value; + final int offset = this.offset; + int i = offset + Math.min(fromIndex, count - 1); + for (; i >= offset ; i--) { + if (value[i] == ch) { return i - offset; } } return -1; + } else { + return lastIndexOfSupplementary(ch, fromIndex); } + } - int max = offset + count; - if (ch <= Character.MAX_CODE_POINT) { - // handle supplementary characters here - char[] surrogates = Character.toChars(ch); - for (; i >= min; i--) { - if (v[i] == surrogates[0]) { - if (i + 1 == max) { - break; - } - if (v[i+1] == surrogates[1]) { - return i - offset; - } + /** + * Handles (rare) calls of lastIndexOf with a supplementary character. + */ + private int lastIndexOfSupplementary(int ch, int fromIndex) { + if (Character.isValidCodePoint(ch)) { + final char[] value = this.value; + final int offset = this.offset; + char hi = Character.highSurrogate(ch); + char lo = Character.lowSurrogate(ch); + int i = offset + Math.min(fromIndex, count - 2); + for (; i >= offset; i--) { + if (value[i] == hi && value[i+1] == lo) { + return i - offset; } } } @@ -1710,18 +1717,17 @@ /** * Returns the index within this string of the first occurrence of the - * specified substring. The integer returned is the smallest value - * <i>k</i> such that: + * specified substring. + * + * <p>The returned index is the smallest value <i>k</i> for which: * <blockquote><pre> * this.startsWith(str, <i>k</i>) * </pre></blockquote> - * is <code>true</code>. + * If no such value of <i>k</i> exists, then {@code -1} is returned. * - * @param str any string. - * @return if the string argument occurs as a substring within this - * object, then the index of the first character of the first - * such substring is returned; if it does not occur as a - * substring, <code>-1</code> is returned. + * @param str the substring to search for. + * @return the index of the first occurrence of the specified substring, + * or {@code -1} if there is no such occurrence. */ public int indexOf(String str) { return indexOf(str, 0); @@ -1729,17 +1735,19 @@ /** * Returns the index within this string of the first occurrence of the - * specified substring, starting at the specified index. The integer - * returned is the smallest value <tt>k</tt> for which: + * specified substring, starting at the specified index. + * + * <p>The returned index is the smallest value <i>k</i> for which: * <blockquote><pre> - * k >= Math.min(fromIndex, this.length()) && this.startsWith(str, k) + * <i>k</i> >= fromIndex && this.startsWith(str, <i>k</i>) * </pre></blockquote> - * If no such value of <i>k</i> exists, then -1 is returned. + * If no such value of <i>k</i> exists, then {@code -1} is returned. * - * @param str the substring for which to search. + * @param str the substring to search for. * @param fromIndex the index from which to start the search. - * @return the index within this string of the first occurrence of the - * specified substring, starting at the specified index. + * @return the index of the first occurrence of the specified substring, + * starting at the specified index, + * or {@code -1} if there is no such occurrence. */ public int indexOf(String str, int fromIndex) { return indexOf(value, offset, count, @@ -1798,20 +1806,19 @@ } /** - * Returns the index within this string of the rightmost occurrence - * of the specified substring. The rightmost empty string "" is - * considered to occur at the index value <code>this.length()</code>. - * The returned index is the largest value <i>k</i> such that + * Returns the index within this string of the last occurrence of the + * specified substring. The last occurrence of the empty string "" + * is considered to occur at the index value {@code this.length()}. + * + * <p>The returned index is the largest value <i>k</i> for which: * <blockquote><pre> - * this.startsWith(str, k) + * this.startsWith(str, <i>k</i>) * </pre></blockquote> - * is true. + * If no such value of <i>k</i> exists, then {@code -1} is returned. * * @param str the substring to search for. - * @return if the string argument occurs one or more times as a substring - * within this object, then the index of the first character of - * the last such substring is returned. If it does not occur as - * a substring, <code>-1</code> is returned. + * @return the index of the last occurrence of the specified substring, + * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str) { return lastIndexOf(str, count); @@ -1820,16 +1827,18 @@ /** * Returns the index within this string of the last occurrence of the * specified substring, searching backward starting at the specified index. - * The integer returned is the largest value <i>k</i> such that: + * + * <p>The returned index is the largest value <i>k</i> for which: * <blockquote><pre> - * k <= Math.min(fromIndex, this.length()) && this.startsWith(str, k) + * <i>k</i> <= fromIndex && this.startsWith(str, <i>k</i>) * </pre></blockquote> - * If no such value of <i>k</i> exists, then -1 is returned. + * If no such value of <i>k</i> exists, then {@code -1} is returned. * * @param str the substring to search for. * @param fromIndex the index to start the search from. - * @return the index within this string of the last occurrence of the - * specified substring. + * @return the index of the last occurrence of the specified substring, + * searching backward from the specified index, + * or {@code -1} if there is no such occurrence. */ public int lastIndexOf(String str, int fromIndex) { return lastIndexOf(value, offset, count,
--- a/src/share/classes/java/lang/System.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/lang/System.java Tue Jul 20 22:21:31 2010 -0700 @@ -69,7 +69,7 @@ * corresponds to keyboard input or another input source specified by * the host environment or user. */ - public final static InputStream in = nullInputStream(); + public final static InputStream in = null; /** * The "standard" output stream. This stream is already @@ -96,7 +96,7 @@ * @see java.io.PrintStream#println(java.lang.Object) * @see java.io.PrintStream#println(java.lang.String) */ - public final static PrintStream out = nullPrintStream(); + public final static PrintStream out = null; /** * The "standard" error output stream. This stream is already @@ -110,7 +110,7 @@ * variable <code>out</code>, has been redirected to a file or other * destination that is typically not continuously monitored. */ - public final static PrintStream err = nullPrintStream(); + public final static PrintStream err = null; /* The security manager for the system. */ @@ -1093,26 +1093,6 @@ public static native String mapLibraryName(String libname); /** - * The following two methods exist because in, out, and err must be - * initialized to null. The compiler, however, cannot be permitted to - * inline access to them, since they are later set to more sensible values - * by initializeSystemClass(). - */ - private static InputStream nullInputStream() throws NullPointerException { - if (currentTimeMillis() > 0) { - return null; - } - throw new NullPointerException(); - } - - private static PrintStream nullPrintStream() throws NullPointerException { - if (currentTimeMillis() > 0) { - return null; - } - throw new NullPointerException(); - } - - /** * Initialize the system class. Called after thread initialization. */ private static void initializeSystemClass() {
--- a/src/share/classes/java/lang/Throwable.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/lang/Throwable.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,6 +25,7 @@ package java.lang; import java.io.*; +import java.util.*; /** * The <code>Throwable</code> class is the superclass of all errors and @@ -102,7 +103,7 @@ * lowLevelOp(); * } catch (LowLevelException le) { * throw (HighLevelException) - new HighLevelException().initCause(le); // Legacy constructor + * new HighLevelException().initCause(le); // Legacy constructor * } * </pre> * @@ -193,6 +194,24 @@ */ /** + * The list of suppressed exceptions, as returned by + * {@link #getSuppressedExceptions()}. + * + * @serial + * @since 1.7 + */ + private List<Throwable> suppressedExceptions = Collections.emptyList(); + + /** Message for trying to suppress a null exception. */ + private static final String NULL_CAUSE_MESSAGE = "Cannot suppress a null exception."; + + /** Caption for labeling causative exception stack traces */ + private static final String CAUSE_CAPTION = "Caused by: "; + + /** Caption for labeling suppressed exception stack traces */ + private static final String SUPPRESSED_CAPTION = "Suppressed: "; + + /** * Constructs a new throwable with <code>null</code> as its detail message. * The cause is not initialized, and may subsequently be initialized by a * call to {@link #initCause}. @@ -469,6 +488,52 @@ * class LowLevelException extends Exception { * } * </pre> + * As of release 7, the platform supports the notion of + * <i>suppressed exceptions</i> (in conjunction with automatic + * resource management blocks). Any exceptions that were + * suppressed in order to deliver an exception are printed out + * beneath the stack trace. The format of this information + * depends on the implementation, but the following example may be + * regarded as typical: + * + * <pre> + * Exception in thread "main" java.lang.Exception: Something happened + * at Foo.bar(Foo.java:10) + * at Foo.main(Foo.java:5) + * Suppressed: Resource$CloseFailException: Resource ID = 0 + * at Resource.close(Resource.java:26) + * at Foo.bar(Foo.java:9) + * ... 1 more + * </pre> + * Note that the "... n more" notation is used on suppressed exceptions + * just at it is used on causes. Unlike causes, suppressed exceptions are + * indented beyond their "containing exceptions." + * + * <p>An exception can have both a cause and one or more suppressed + * exceptions: + * <pre> + * Exception in thread "main" java.lang.Exception: Main block + * at Foo3.main(Foo3.java:7) + * Suppressed: Resource$CloseFailException: Resource ID = 2 + * at Resource.close(Resource.java:26) + * at Foo3.main(Foo3.java:5) + * Suppressed: Resource$CloseFailException: Resource ID = 1 + * at Resource.close(Resource.java:26) + * at Foo3.main(Foo3.java:5) + * Caused by: java.lang.Exception: I did it + * at Foo3.main(Foo3.java:8) + * </pre> + * Likewise, a suppressed exception can have a cause: + * <pre> + * Exception in thread "main" java.lang.Exception: Main block + * at Foo4.main(Foo4.java:6) + * Suppressed: Resource2$CloseFailException: Resource ID = 1 + * at Resource2.close(Resource2.java:20) + * at Foo4.main(Foo4.java:5) + * Caused by: java.lang.Exception: Rats, you caught me + * at Resource2$CloseFailException.<init>(Resource2.java:45) + * ... 2 more + * </pre> */ public void printStackTrace() { printStackTrace(System.err); @@ -480,44 +545,71 @@ * @param s <code>PrintStream</code> to use for output */ public void printStackTrace(PrintStream s) { - synchronized (s) { + printStackTrace(new WrappedPrintStream(s)); + } + + private void printStackTrace(PrintStreamOrWriter s) { + Set<Throwable> dejaVu = new HashSet<Throwable>(); + dejaVu.add(this); + + synchronized (s.lock()) { + // Print our stack trace s.println(this); StackTraceElement[] trace = getOurStackTrace(); - for (int i=0; i < trace.length; i++) - s.println("\tat " + trace[i]); + for (StackTraceElement traceElement : trace) + s.println("\tat " + traceElement); + // Print suppressed exceptions, if any + for (Throwable se : suppressedExceptions) + se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, "\t", dejaVu); + + // Print cause, if any Throwable ourCause = getCause(); if (ourCause != null) - ourCause.printStackTraceAsCause(s, trace); + ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, "", dejaVu); } } /** - * Print our stack trace as a cause for the specified stack trace. + * Print our stack trace as an enclosed exception for the specified + * stack trace. */ - private void printStackTraceAsCause(PrintStream s, - StackTraceElement[] causedTrace) - { - // assert Thread.holdsLock(s); + private void printEnclosedStackTrace(PrintStreamOrWriter s, + StackTraceElement[] enclosingTrace, + String caption, + String prefix, + Set<Throwable> dejaVu) { + assert Thread.holdsLock(s.lock()); + if (dejaVu.contains(this)) { + s.println("\t[CIRCULAR REFERENCE:" + this + "]"); + } else { + dejaVu.add(this); + // Compute number of frames in common between this and enclosing trace + StackTraceElement[] trace = getOurStackTrace(); + int m = trace.length - 1; + int n = enclosingTrace.length - 1; + while (m >= 0 && n >=0 && trace[m].equals(enclosingTrace[n])) { + m--; n--; + } + int framesInCommon = trace.length - 1 - m; - // Compute number of frames in common between this and caused - StackTraceElement[] trace = getOurStackTrace(); - int m = trace.length-1, n = causedTrace.length-1; - while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) { - m--; n--; + // Print our stack trace + s.println(prefix + caption + this); + for (int i = 0; i <= m; i++) + s.println(prefix + "\tat " + trace[i]); + if (framesInCommon != 0) + s.println(prefix + "\t... " + framesInCommon + " more"); + + // Print suppressed exceptions, if any + for (Throwable se : suppressedExceptions) + se.printEnclosedStackTrace(s, trace, SUPPRESSED_CAPTION, + prefix +"\t", dejaVu); + + // Print cause, if any + Throwable ourCause = getCause(); + if (ourCause != null) + ourCause.printEnclosedStackTrace(s, trace, CAUSE_CAPTION, prefix, dejaVu); } - int framesInCommon = trace.length - 1 - m; - - s.println("Caused by: " + this); - for (int i=0; i <= m; i++) - s.println("\tat " + trace[i]); - if (framesInCommon != 0) - s.println("\t... " + framesInCommon + " more"); - - // Recurse if we have a cause - Throwable ourCause = getCause(); - if (ourCause != null) - ourCause.printStackTraceAsCause(s, trace); } /** @@ -528,44 +620,51 @@ * @since JDK1.1 */ public void printStackTrace(PrintWriter s) { - synchronized (s) { - s.println(this); - StackTraceElement[] trace = getOurStackTrace(); - for (int i=0; i < trace.length; i++) - s.println("\tat " + trace[i]); - - Throwable ourCause = getCause(); - if (ourCause != null) - ourCause.printStackTraceAsCause(s, trace); - } + printStackTrace(new WrappedPrintWriter(s)); } /** - * Print our stack trace as a cause for the specified stack trace. + * Wrapper class for PrintStream and PrintWriter to enable a single + * implementation of printStackTrace. */ - private void printStackTraceAsCause(PrintWriter s, - StackTraceElement[] causedTrace) - { - // assert Thread.holdsLock(s); + private abstract static class PrintStreamOrWriter { + /** Returns the object to be locked when using this StreamOrWriter */ + abstract Object lock(); + + /** Prints the specified string as a line on this StreamOrWriter */ + abstract void println(Object o); + } - // Compute number of frames in common between this and caused - StackTraceElement[] trace = getOurStackTrace(); - int m = trace.length-1, n = causedTrace.length-1; - while (m >= 0 && n >=0 && trace[m].equals(causedTrace[n])) { - m--; n--; + private static class WrappedPrintStream extends PrintStreamOrWriter { + private final PrintStream printStream; + + WrappedPrintStream(PrintStream printStream) { + this.printStream = printStream; + } + + Object lock() { + return printStream; } - int framesInCommon = trace.length - 1 - m; + + void println(Object o) { + printStream.println(o); + } + } + + private static class WrappedPrintWriter extends PrintStreamOrWriter { + private final PrintWriter printWriter; - s.println("Caused by: " + this); - for (int i=0; i <= m; i++) - s.println("\tat " + trace[i]); - if (framesInCommon != 0) - s.println("\t... " + framesInCommon + " more"); + WrappedPrintWriter(PrintWriter printWriter) { + this.printWriter = printWriter; + } - // Recurse if we have a cause - Throwable ourCause = getCause(); - if (ourCause != null) - ourCause.printStackTraceAsCause(s, trace); + Object lock() { + return printWriter; + } + + void println(Object o) { + printWriter.println(o); + } } /** @@ -667,10 +766,60 @@ */ native StackTraceElement getStackTraceElement(int index); - private synchronized void writeObject(java.io.ObjectOutputStream s) + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); // read in all fields + List<Throwable> suppressed = Collections.emptyList(); + if (suppressedExceptions != null && + !suppressedExceptions.isEmpty()) { // Copy Throwables to new list + suppressed = new ArrayList<Throwable>(); + for(Throwable t : suppressedExceptions) { + if (t == null) + throw new NullPointerException(NULL_CAUSE_MESSAGE); + suppressed.add(t); + } + } + suppressedExceptions = suppressed; + } + + private synchronized void writeObject(ObjectOutputStream s) throws IOException { getOurStackTrace(); // Ensure that stackTrace field is initialized. s.defaultWriteObject(); } + + /** + * Adds the specified exception to the list of exceptions that + * were suppressed, typically by the automatic resource management + * statement, in order to deliver this exception. + * + * @param exception the exception to be added to the list of + * suppressed exceptions + * @throws NullPointerException if {@code exception} is null + * @since 1.7 + */ + public synchronized void addSuppressedException(Throwable exception) { + if (exception == null) + throw new NullPointerException(NULL_CAUSE_MESSAGE); + + if (suppressedExceptions.size() == 0) + suppressedExceptions = new ArrayList<Throwable>(); + suppressedExceptions.add(exception); + } + + private static final Throwable[] EMPTY_THROWABLE_ARRAY = new Throwable[0]; + + /** + * Returns an array containing all of the exceptions that were + * suppressed, typically by the automatic resource management + * statement, in order to deliver this exception. + * + * @return an array containing all of the exceptions that were + * suppressed to deliver this exception. + * @since 1.7 + */ + public Throwable[] getSuppressedExceptions() { + return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY); + } }
--- a/src/share/classes/java/net/Inet6Address.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/net/Inet6Address.java Tue Jul 20 22:21:31 2010 -0700 @@ -427,8 +427,9 @@ try { scope_id = deriveNumericScope (scope_ifname); } catch (UnknownHostException e) { - // should not happen - assert false; + // typically should not happen, but it may be that + // the machine being used for deserialization has + // the same interface name but without IPv6 configured. } } } catch (SocketException e) {}
--- a/src/share/classes/java/nio/Bits.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/nio/Bits.java Tue Jul 20 22:21:31 2010 -0700 @@ -41,25 +41,19 @@ // -- Swapping -- static short swap(short x) { - return (short)((x << 8) | - ((char)x >>> 8)); + return Short.reverseBytes(x); } static char swap(char x) { - return (char)((x << 8) | - (x >>> 8)); + return Character.reverseBytes(x); } static int swap(int x) { - return ((x << 24) | - ((x & 0x0000ff00) << 8) | - ((x & 0x00ff0000) >>> 8) | - (x >>> 24)); + return Integer.reverseBytes(x); } static long swap(long x) { - return (((long)swap((int)x) << 32) | - ((long)swap((int)(x >>> 32)) & 0xffffffffL)); + return Long.reverseBytes(x); } @@ -71,52 +65,52 @@ static char getCharL(ByteBuffer bb, int bi) { return makeChar(bb._get(bi + 1), - bb._get(bi + 0)); + bb._get(bi )); } static char getCharL(long a) { return makeChar(_get(a + 1), - _get(a + 0)); + _get(a )); } static char getCharB(ByteBuffer bb, int bi) { - return makeChar(bb._get(bi + 0), + return makeChar(bb._get(bi ), bb._get(bi + 1)); } static char getCharB(long a) { - return makeChar(_get(a + 0), + return makeChar(_get(a ), _get(a + 1)); } static char getChar(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getCharB(bb, bi) : getCharL(bb, bi)); + return bigEndian ? getCharB(bb, bi) : getCharL(bb, bi); } static char getChar(long a, boolean bigEndian) { - return (bigEndian ? getCharB(a) : getCharL(a)); + return bigEndian ? getCharB(a) : getCharL(a); } private static byte char1(char x) { return (byte)(x >> 8); } - private static byte char0(char x) { return (byte)(x >> 0); } + private static byte char0(char x) { return (byte)(x ); } static void putCharL(ByteBuffer bb, int bi, char x) { - bb._put(bi + 0, char0(x)); + bb._put(bi , char0(x)); bb._put(bi + 1, char1(x)); } static void putCharL(long a, char x) { - _put(a + 0, char0(x)); + _put(a , char0(x)); _put(a + 1, char1(x)); } static void putCharB(ByteBuffer bb, int bi, char x) { - bb._put(bi + 0, char1(x)); + bb._put(bi , char1(x)); bb._put(bi + 1, char0(x)); } static void putCharB(long a, char x) { - _put(a + 0, char1(x)); + _put(a , char1(x)); _put(a + 1, char0(x)); } @@ -143,52 +137,52 @@ static short getShortL(ByteBuffer bb, int bi) { return makeShort(bb._get(bi + 1), - bb._get(bi + 0)); + bb._get(bi )); } static short getShortL(long a) { return makeShort(_get(a + 1), - _get(a)); + _get(a )); } static short getShortB(ByteBuffer bb, int bi) { - return makeShort(bb._get(bi + 0), + return makeShort(bb._get(bi ), bb._get(bi + 1)); } static short getShortB(long a) { - return makeShort(_get(a), + return makeShort(_get(a ), _get(a + 1)); } static short getShort(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getShortB(bb, bi) : getShortL(bb, bi)); + return bigEndian ? getShortB(bb, bi) : getShortL(bb, bi); } static short getShort(long a, boolean bigEndian) { - return (bigEndian ? getShortB(a) : getShortL(a)); + return bigEndian ? getShortB(a) : getShortL(a); } private static byte short1(short x) { return (byte)(x >> 8); } - private static byte short0(short x) { return (byte)(x >> 0); } + private static byte short0(short x) { return (byte)(x ); } static void putShortL(ByteBuffer bb, int bi, short x) { - bb._put(bi + 0, short0(x)); + bb._put(bi , short0(x)); bb._put(bi + 1, short1(x)); } static void putShortL(long a, short x) { - _put(a, short0(x)); + _put(a , short0(x)); _put(a + 1, short1(x)); } static void putShortB(ByteBuffer bb, int bi, short x) { - bb._put(bi + 0, short1(x)); + bb._put(bi , short1(x)); bb._put(bi + 1, short0(x)); } static void putShortB(long a, short x) { - _put(a, short1(x)); + _put(a , short1(x)); _put(a + 1, short0(x)); } @@ -210,76 +204,76 @@ // -- get/put int -- static private int makeInt(byte b3, byte b2, byte b1, byte b0) { - return (((b3 & 0xff) << 24) | + return (((b3 ) << 24) | ((b2 & 0xff) << 16) | ((b1 & 0xff) << 8) | - ((b0 & 0xff) << 0)); + ((b0 & 0xff) )); } static int getIntL(ByteBuffer bb, int bi) { return makeInt(bb._get(bi + 3), bb._get(bi + 2), bb._get(bi + 1), - bb._get(bi + 0)); + bb._get(bi )); } static int getIntL(long a) { return makeInt(_get(a + 3), _get(a + 2), _get(a + 1), - _get(a + 0)); + _get(a )); } static int getIntB(ByteBuffer bb, int bi) { - return makeInt(bb._get(bi + 0), + return makeInt(bb._get(bi ), bb._get(bi + 1), bb._get(bi + 2), bb._get(bi + 3)); } static int getIntB(long a) { - return makeInt(_get(a + 0), + return makeInt(_get(a ), _get(a + 1), _get(a + 2), _get(a + 3)); } static int getInt(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getIntB(bb, bi) : getIntL(bb, bi)); + return bigEndian ? getIntB(bb, bi) : getIntL(bb, bi) ; } static int getInt(long a, boolean bigEndian) { - return (bigEndian ? getIntB(a) : getIntL(a)); + return bigEndian ? getIntB(a) : getIntL(a) ; } private static byte int3(int x) { return (byte)(x >> 24); } private static byte int2(int x) { return (byte)(x >> 16); } private static byte int1(int x) { return (byte)(x >> 8); } - private static byte int0(int x) { return (byte)(x >> 0); } + private static byte int0(int x) { return (byte)(x ); } static void putIntL(ByteBuffer bb, int bi, int x) { bb._put(bi + 3, int3(x)); bb._put(bi + 2, int2(x)); bb._put(bi + 1, int1(x)); - bb._put(bi + 0, int0(x)); + bb._put(bi , int0(x)); } static void putIntL(long a, int x) { _put(a + 3, int3(x)); _put(a + 2, int2(x)); _put(a + 1, int1(x)); - _put(a + 0, int0(x)); + _put(a , int0(x)); } static void putIntB(ByteBuffer bb, int bi, int x) { - bb._put(bi + 0, int3(x)); + bb._put(bi , int3(x)); bb._put(bi + 1, int2(x)); bb._put(bi + 2, int1(x)); bb._put(bi + 3, int0(x)); } static void putIntB(long a, int x) { - _put(a + 0, int3(x)); + _put(a , int3(x)); _put(a + 1, int2(x)); _put(a + 2, int1(x)); _put(a + 3, int0(x)); @@ -305,14 +299,14 @@ static private long makeLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) { - return ((((long)b7 & 0xff) << 56) | + return ((((long)b7 ) << 56) | (((long)b6 & 0xff) << 48) | (((long)b5 & 0xff) << 40) | (((long)b4 & 0xff) << 32) | (((long)b3 & 0xff) << 24) | (((long)b2 & 0xff) << 16) | (((long)b1 & 0xff) << 8) | - (((long)b0 & 0xff) << 0)); + (((long)b0 & 0xff) )); } static long getLongL(ByteBuffer bb, int bi) { @@ -323,7 +317,7 @@ bb._get(bi + 3), bb._get(bi + 2), bb._get(bi + 1), - bb._get(bi + 0)); + bb._get(bi )); } static long getLongL(long a) { @@ -334,11 +328,11 @@ _get(a + 3), _get(a + 2), _get(a + 1), - _get(a + 0)); + _get(a )); } static long getLongB(ByteBuffer bb, int bi) { - return makeLong(bb._get(bi + 0), + return makeLong(bb._get(bi ), bb._get(bi + 1), bb._get(bi + 2), bb._get(bi + 3), @@ -349,7 +343,7 @@ } static long getLongB(long a) { - return makeLong(_get(a + 0), + return makeLong(_get(a ), _get(a + 1), _get(a + 2), _get(a + 3), @@ -360,11 +354,11 @@ } static long getLong(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getLongB(bb, bi) : getLongL(bb, bi)); + return bigEndian ? getLongB(bb, bi) : getLongL(bb, bi); } static long getLong(long a, boolean bigEndian) { - return (bigEndian ? getLongB(a) : getLongL(a)); + return bigEndian ? getLongB(a) : getLongL(a); } private static byte long7(long x) { return (byte)(x >> 56); } @@ -374,7 +368,7 @@ private static byte long3(long x) { return (byte)(x >> 24); } private static byte long2(long x) { return (byte)(x >> 16); } private static byte long1(long x) { return (byte)(x >> 8); } - private static byte long0(long x) { return (byte)(x >> 0); } + private static byte long0(long x) { return (byte)(x ); } static void putLongL(ByteBuffer bb, int bi, long x) { bb._put(bi + 7, long7(x)); @@ -384,7 +378,7 @@ bb._put(bi + 3, long3(x)); bb._put(bi + 2, long2(x)); bb._put(bi + 1, long1(x)); - bb._put(bi + 0, long0(x)); + bb._put(bi , long0(x)); } static void putLongL(long a, long x) { @@ -395,11 +389,11 @@ _put(a + 3, long3(x)); _put(a + 2, long2(x)); _put(a + 1, long1(x)); - _put(a + 0, long0(x)); + _put(a , long0(x)); } static void putLongB(ByteBuffer bb, int bi, long x) { - bb._put(bi + 0, long7(x)); + bb._put(bi , long7(x)); bb._put(bi + 1, long6(x)); bb._put(bi + 2, long5(x)); bb._put(bi + 3, long4(x)); @@ -410,7 +404,7 @@ } static void putLongB(long a, long x) { - _put(a + 0, long7(x)); + _put(a , long7(x)); _put(a + 1, long6(x)); _put(a + 2, long5(x)); _put(a + 3, long4(x)); @@ -454,11 +448,11 @@ } static float getFloat(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi)); + return bigEndian ? getFloatB(bb, bi) : getFloatL(bb, bi); } static float getFloat(long a, boolean bigEndian) { - return (bigEndian ? getFloatB(a) : getFloatL(a)); + return bigEndian ? getFloatB(a) : getFloatL(a); } static void putFloatL(ByteBuffer bb, int bi, float x) { @@ -511,11 +505,11 @@ } static double getDouble(ByteBuffer bb, int bi, boolean bigEndian) { - return (bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi)); + return bigEndian ? getDoubleB(bb, bi) : getDoubleL(bb, bi); } static double getDouble(long a, boolean bigEndian) { - return (bigEndian ? getDoubleB(a) : getDoubleL(a)); + return bigEndian ? getDoubleB(a) : getDoubleL(a); } static void putDoubleL(ByteBuffer bb, int bi, double x) { @@ -794,7 +788,7 @@ static native void copyFromIntArray(Object src, long srcPos, long dstAddr, long length); static native void copyToIntArray(long srcAddr, Object dst, long dstPos, - long length); + long length); static native void copyFromLongArray(Object src, long srcPos, long dstAddr, long length);
--- a/src/share/classes/java/nio/channels/FileLock.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/nio/channels/FileLock.java Tue Jul 20 22:21:31 2010 -0700 @@ -116,7 +116,7 @@ * @since 1.4 */ -public abstract class FileLock { +public abstract class FileLock implements AutoCloseable { private final Channel channel; private final long position; @@ -299,6 +299,17 @@ public abstract void release() throws IOException; /** + * This method invokes the {@link #release} method. It was added + * to the class so that it could be used in conjunction with the + * automatic resource management block construct. + * + * @since 1.7 + */ + public final void close() throws IOException { + release(); + } + + /** * Returns a string describing the range, type, and validity of this lock. * * @return A descriptive string
--- a/src/share/classes/java/util/DualPivotQuicksort.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/util/DualPivotQuicksort.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ /** * This class implements the Dual-Pivot Quicksort algorithm by - * Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. The algorithm + * Vladimir Yaroslavskiy, Jon Bentley, and Josh Bloch. The algorithm * offers O(n log(n)) performance on many data sets that cause other * quicksorts to degrade to quadratic performance, and is typically * faster than traditional (one-pivot) Quicksort implementations. @@ -36,7 +36,8 @@ * @author Jon Bentley * @author Josh Bloch * - * @version 2009.11.29 m765.827.12i + * @version 2010.06.21 m765.827.12i:5\7 + * @since 1.7 */ final class DualPivotQuicksort { @@ -68,7 +69,7 @@ private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768; /* - * Sorting methods for 7 primitive types. + * Sorting methods for seven primitive types. */ /** @@ -77,7 +78,7 @@ * @param a the array to be sorted */ public static void sort(int[] a) { - doSort(a, 0, a.length - 1); + sort(a, 0, a.length - 1, true); } /** @@ -95,98 +96,132 @@ */ public static void sort(int[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); - doSort(a, fromIndex, toIndex - 1); + sort(a, fromIndex, toIndex - 1, true); } /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in that the - * {@code right} index is inclusive, and it does no range checking - * on {@code left} or {@code right}. + * Sorts the specified range of the array into ascending order by the + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range */ - private static void doSort(int[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - int ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } + private static void sort(int[] a, int left, int right, boolean leftmost) { + int length = right - left + 1; - /** - * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. - * - * @param a the array to be sorted - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void dualPivotQuicksort(int[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + int ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + int ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } + + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; - // Sort these elements using a 5-element sorting network - int ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { int t = a[e2]; a[e2] = a[e1]; a[e1] = t; } - if (ae1 > ae2) { int t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { int t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { int t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { int t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { int t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; } - - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + if (a[e3] < a[e2]) { int t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { int t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { int t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - int pivot1 = ae2; a[e2] = a[left]; - int pivot2 = ae4; a[e4] = a[right]; + int pivot1 = a[e2]; + int pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -194,16 +229,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { int ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -213,26 +246,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + int ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = pivot1; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -240,20 +354,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - int ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + int ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -261,92 +374,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ a[k] = pivot1; - a[great--] = ak; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - int ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -355,7 +409,7 @@ * @param a the array to be sorted */ public static void sort(long[] a) { - doSort(a, 0, a.length - 1); + sort(a, 0, a.length - 1, true); } /** @@ -373,98 +427,132 @@ */ public static void sort(long[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); - doSort(a, fromIndex, toIndex - 1); + sort(a, fromIndex, toIndex - 1, true); } /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in that the - * {@code right} index is inclusive, and it does no range checking on - * {@code left} or {@code right}. + * Sorts the specified range of the array into ascending order by the + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range */ - private static void doSort(long[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - long ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } + private static void sort(long[] a, int left, int right, boolean leftmost) { + int length = right - left + 1; - /** - * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. - * - * @param a the array to be sorted - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void dualPivotQuicksort(long[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + long ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + long ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } + + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; - // Sort these elements using a 5-element sorting network - long ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { long t = a[e2]; a[e2] = a[e1]; a[e1] = t; } - if (ae1 > ae2) { long t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { long t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { long t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { long t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { long t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; } - - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + if (a[e3] < a[e2]) { long t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { long t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { long t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - long pivot1 = ae2; a[e2] = a[left]; - long pivot2 = ae4; a[e4] = a[right]; + long pivot1 = a[e2]; + long pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -472,16 +560,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { long ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -491,26 +577,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + long ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = pivot1; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -518,20 +685,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - long ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + long ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -539,92 +705,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ a[k] = pivot1; - a[great--] = ak; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - long ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -633,7 +740,11 @@ * @param a the array to be sorted */ public static void sort(short[] a) { - doSort(a, 0, a.length - 1); + if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { + countingSort(a, 0, a.length - 1); + } else { + sort(a, 0, a.length - 1, true); + } } /** @@ -651,115 +762,166 @@ */ public static void sort(short[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); - doSort(a, fromIndex, toIndex - 1); + + if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { + countingSort(a, fromIndex, toIndex - 1); + } else { + sort(a, fromIndex, toIndex - 1, true); + } } /** The number of distinct short values. */ private static final int NUM_SHORT_VALUES = 1 << 16; /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in that the - * {@code right} index is inclusive, and it does no range checking on - * {@code left} or {@code right}. - * - * @param a the array to be sorted - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void doSort(short[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - short ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { - // Use counting sort on huge arrays - int[] count = new int[NUM_SHORT_VALUES]; - - for (int i = left; i <= right; i++) { - count[a[i] - Short.MIN_VALUE]++; - } - for (int i = 0, k = left; i < count.length && k <= right; i++) { - short value = (short) (i + Short.MIN_VALUE); - - for (int s = count[i]; s > 0; s--) { - a[k++] = value; - } - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } - - /** - * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. + * Sorts the specified range of the array by counting sort. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted */ - private static void dualPivotQuicksort(short[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; - int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + private static void countingSort(short[] a, int left, int right) { + int[] count = new int[NUM_SHORT_VALUES]; + + for (int i = left; i <= right; i++) { + count[a[i] - Short.MIN_VALUE]++; + } + for (int i = NUM_SHORT_VALUES - 1, k = right; k >= left; i--) { + while (count[i] == 0) { + i--; + } + short value = (short) (i + Short.MIN_VALUE); + int s = count[i]; - // Sort these elements using a 5-element sorting network - short ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + do { + a[k--] = value; + } while (--s > 0); + } + } + + /** + * Sorts the specified range of the array into ascending order by the + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. + * + * @param a the array to be sorted + * @param left the index of the first element, inclusive, to be sorted + * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range + */ + private static void sort(short[] a, int left, int right,boolean leftmost) { + int length = right - left + 1; - if (ae1 > ae2) { short t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { short t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { short t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { short t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { short t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; } + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + short ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + short ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ + int e3 = (left + right) >>> 1; // The midpoint + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; + + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { short t = a[e2]; a[e2] = a[e1]; a[e1] = t; } + + if (a[e3] < a[e2]) { short t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { short t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { short t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - short pivot1 = ae2; a[e2] = a[left]; - short pivot2 = ae4; a[e4] = a[right]; + short pivot1 = a[e2]; + short pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -767,16 +929,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { short ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -786,26 +946,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + short ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = pivot1; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -813,20 +1054,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - short ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + short ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -834,92 +1074,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ a[k] = pivot1; - a[great--] = ak; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - short ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -928,7 +1109,11 @@ * @param a the array to be sorted */ public static void sort(char[] a) { - doSort(a, 0, a.length - 1); + if (a.length > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { + countingSort(a, 0, a.length - 1); + } else { + sort(a, 0, a.length - 1, true); + } } /** @@ -946,113 +1131,166 @@ */ public static void sort(char[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); - doSort(a, fromIndex, toIndex - 1); + + if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { + countingSort(a, fromIndex, toIndex - 1); + } else { + sort(a, fromIndex, toIndex - 1, true); + } } /** The number of distinct char values. */ private static final int NUM_CHAR_VALUES = 1 << 16; /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in that the - * {@code right} index is inclusive, and it does no range checking on - * {@code left} or {@code right}. - * - * @param a the array to be sorted - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void doSort(char[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - char ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) { - // Use counting sort on huge arrays - int[] count = new int[NUM_CHAR_VALUES]; - - for (int i = left; i <= right; i++) { - count[a[i]]++; - } - for (int i = 0, k = left; i < count.length && k <= right; i++) { - for (int s = count[i]; s > 0; s--) { - a[k++] = (char) i; - } - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } - - /** - * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. + * Sorts the specified range of the array by counting sort. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted */ - private static void dualPivotQuicksort(char[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; - int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + private static void countingSort(char[] a, int left, int right) { + int[] count = new int[NUM_CHAR_VALUES]; + + for (int i = left; i <= right; i++) { + count[a[i]]++; + } + for (int i = 0, k = left; k <= right; i++) { + while (count[i] == 0) { + i++; + } + char value = (char) i; + int s = count[i]; - // Sort these elements using a 5-element sorting network - char ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + do { + a[k++] = value; + } while (--s > 0); + } + } + + /** + * Sorts the specified range of the array into ascending order by the + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. + * + * @param a the array to be sorted + * @param left the index of the first element, inclusive, to be sorted + * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range + */ + private static void sort(char[] a, int left, int right, boolean leftmost) { + int length = right - left + 1; - if (ae1 > ae2) { char t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { char t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { char t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { char t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { char t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; } + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + char ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + char ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ + int e3 = (left + right) >>> 1; // The midpoint + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; + + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { char t = a[e2]; a[e2] = a[e1]; a[e1] = t; } + + if (a[e3] < a[e2]) { char t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { char t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { char t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - char pivot1 = ae2; a[e2] = a[left]; - char pivot2 = ae4; a[e4] = a[right]; + char pivot1 = a[e2]; + char pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1060,16 +1298,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { char ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -1079,26 +1315,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + char ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = pivot1; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1106,20 +1423,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - char ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + char ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1127,92 +1443,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ a[k] = pivot1; - a[great--] = ak; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - char ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -1221,7 +1478,11 @@ * @param a the array to be sorted */ public static void sort(byte[] a) { - doSort(a, 0, a.length - 1); + if (a.length > COUNTING_SORT_THRESHOLD_FOR_BYTE) { + countingSort(a, 0, a.length - 1); + } else { + sort(a, 0, a.length - 1, true); + } } /** @@ -1239,115 +1500,166 @@ */ public static void sort(byte[] a, int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); - doSort(a, fromIndex, toIndex - 1); + + if (toIndex - fromIndex > COUNTING_SORT_THRESHOLD_FOR_BYTE) { + countingSort(a, fromIndex, toIndex - 1); + } else { + sort(a, fromIndex, toIndex - 1, true); + } } /** The number of distinct byte values. */ private static final int NUM_BYTE_VALUES = 1 << 8; /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in that the - * {@code right} index is inclusive, and it does no range checking on - * {@code left} or {@code right}. - * - * @param a the array to be sorted - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void doSort(byte[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - byte ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) { - // Use counting sort on huge arrays - int[] count = new int[NUM_BYTE_VALUES]; - - for (int i = left; i <= right; i++) { - count[a[i] - Byte.MIN_VALUE]++; - } - for (int i = 0, k = left; i < count.length && k <= right; i++) { - byte value = (byte) (i + Byte.MIN_VALUE); - - for (int s = count[i]; s > 0; s--) { - a[k++] = value; - } - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } - - /** - * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. + * Sorts the specified range of the array by counting sort. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted */ - private static void dualPivotQuicksort(byte[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; - int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + private static void countingSort(byte[] a, int left, int right) { + int[] count = new int[NUM_BYTE_VALUES]; + + for (int i = left; i <= right; i++) { + count[a[i] - Byte.MIN_VALUE]++; + } + for (int i = NUM_BYTE_VALUES - 1, k = right; k >= left; i--) { + while (count[i] == 0) { + i--; + } + byte value = (byte) (i + Byte.MIN_VALUE); + int s = count[i]; - // Sort these elements using a 5-element sorting network - byte ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + do { + a[k--] = value; + } while (--s > 0); + } + } + + /** + * Sorts the specified range of the array into ascending order by the + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. + * + * @param a the array to be sorted + * @param left the index of the first element, inclusive, to be sorted + * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range + */ + private static void sort(byte[] a, int left, int right, boolean leftmost) { + int length = right - left + 1; - if (ae1 > ae2) { byte t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { byte t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { byte t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { byte t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { byte t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; } + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + byte ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + byte ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ + int e3 = (left + right) >>> 1; // The midpoint + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; + + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { byte t = a[e2]; a[e2] = a[e1]; a[e1] = t; } + + if (a[e3] < a[e2]) { byte t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { byte t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { byte t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - byte pivot1 = ae2; a[e2] = a[left]; - byte pivot2 = ae4; a[e4] = a[right]; + byte pivot1 = a[e2]; + byte pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1355,16 +1667,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { byte ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -1374,26 +1684,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + byte ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = pivot1; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1401,20 +1792,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - byte ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + byte ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1422,92 +1812,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ a[k] = pivot1; - a[great--] = ak; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - byte ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -1531,7 +1862,7 @@ * Sorts the specified range of the array into ascending order. The range * to be sorted extends from the index {@code fromIndex}, inclusive, to * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex}, - * the range to be sorted is empty and the call is a no-op). + * the range to be sorted is empty (and the call is a no-op). * * <p>The {@code <} relation does not provide a total order on all float * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN} @@ -1565,162 +1896,207 @@ */ private static void sortNegZeroAndNaN(float[] a, int left, int right) { /* - * Phase 1: Count negative zeros and move NaNs to end of array + * Phase 1: Move NaNs to the end of the array. */ - final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f); - int numNegativeZeros = 0; - int n = right; - - for (int k = left; k <= n; k++) { + while (left <= right && Float.isNaN(a[right])) { + right--; + } + for (int k = right - 1; k >= left; k--) { float ak = a[k]; - if (ak == 0.0f && NEGATIVE_ZERO == Float.floatToIntBits(ak)) { - a[k] = 0.0f; - numNegativeZeros++; - } else if (ak != ak) { // i.e., ak is NaN - a[k--] = a[n]; - a[n--] = Float.NaN; + if (ak != ak) { // a[k] is NaN + a[k] = a[right]; + a[right] = ak; + right--; } } /* - * Phase 2: Sort everything except NaNs (which are already in place) + * Phase 2: Sort everything except NaNs (which are already in place). */ - doSort(a, left, n); + sort(a, left, right, true); /* - * Phase 3: Turn positive zeros back into negative zeros as appropriate + * Phase 3: Place negative zeros before positive zeros. */ - if (numNegativeZeros == 0) { - return; - } - - // Find first zero element - int zeroIndex = findAnyZero(a, left, n); - - for (int i = zeroIndex - 1; i >= left && a[i] == 0.0f; i--) { - zeroIndex = i; - } + int hi = right; - // Turn the right number of positive zeros back into negative zeros - for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) { - a[i] = -0.0f; - } - } - - /** - * Returns the index of some zero element in the specified range via - * binary search. The range is assumed to be sorted, and must contain - * at least one zero. - * - * @param a the array to be searched - * @param low the index of the first element, inclusive, to be searched - * @param high the index of the last element, inclusive, to be searched - */ - private static int findAnyZero(float[] a, int low, int high) { - while (true) { - int middle = (low + high) >>> 1; + /* + * Search first zero, or first positive, or last negative element. + */ + while (left < hi) { + int middle = (left + hi) >>> 1; float middleValue = a[middle]; if (middleValue < 0.0f) { - low = middle + 1; - } else if (middleValue > 0.0f) { - high = middle - 1; - } else { // middleValue == 0.0f - return middle; + left = middle + 1; + } else { + hi = middle; + } + } + + /* + * Skip the last negative value (if any) or all leading negative zeros. + */ + while (left <= right && Float.floatToRawIntBits(a[left]) < 0) { + left++; + } + + /* + * Move negative zeros to the beginning of the sub-range. + * + * Partitioning: + * + * +---------------------------------------------------+ + * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) | + * +---------------------------------------------------+ + * ^ ^ ^ + * | | | + * left p k + * + * Invariants: + * + * all in (*, left) < 0.0 + * all in [left, p) == -0.0 + * all in [p, k) == 0.0 + * all in [k, right] >= 0.0 + * + * Pointer k is the first index of ?-part. + */ + for (int k = left + 1, p = left; k <= right; k++) { + float ak = a[k]; + if (ak != 0.0f) { + break; + } + if (Float.floatToRawIntBits(ak) < 0) { // ak is -0.0f + a[k] = 0.0f; + a[p++] = -0.0f; } } } /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in three ways: - * {@code right} index is inclusive, it does no range checking on - * {@code left} or {@code right}, and it does not handle negative - * zeros or NaNs in the array. - * - * @param a the array to be sorted, which must not contain -0.0f or NaN - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void doSort(float[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - float ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } - - /** * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range */ - private static void dualPivotQuicksort(float[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; - int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + private static void sort(float[] a, int left, int right,boolean leftmost) { + int length = right - left + 1; - // Sort these elements using a 5-element sorting network - float ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + float ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + float ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } - if (ae1 > ae2) { float t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { float t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { float t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { float t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { float t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; } + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ + int e3 = (left + right) >>> 1; // The midpoint + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { float t = a[e2]; a[e2] = a[e1]; a[e1] = t; } + + if (a[e3] < a[e2]) { float t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { float t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { float t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - float pivot1 = ae2; a[e2] = a[left]; - float pivot2 = ae4; a[e4] = a[right]; + float pivot1 = a[e2]; + float pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1728,16 +2104,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { float ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -1747,26 +2121,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + float ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = a[great]; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -1774,20 +2229,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - float ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + float ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -1795,92 +2249,33 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 - a[k] = pivot1; - a[great--] = ak; + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ + a[k] = a[great]; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - float ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** @@ -1938,162 +2333,207 @@ */ private static void sortNegZeroAndNaN(double[] a, int left, int right) { /* - * Phase 1: Count negative zeros and move NaNs to end of array + * Phase 1: Move NaNs to the end of the array. */ - final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d); - int numNegativeZeros = 0; - int n = right; - - for (int k = left; k <= n; k++) { + while (left <= right && Double.isNaN(a[right])) { + right--; + } + for (int k = right - 1; k >= left; k--) { double ak = a[k]; - if (ak == 0.0d && NEGATIVE_ZERO == Double.doubleToLongBits(ak)) { - a[k] = 0.0d; - numNegativeZeros++; - } else if (ak != ak) { // i.e., ak is NaN - a[k--] = a[n]; - a[n--] = Double.NaN; + if (ak != ak) { // a[k] is NaN + a[k] = a[right]; + a[right] = ak; + right--; } } /* - * Phase 2: Sort everything except NaNs (which are already in place) + * Phase 2: Sort everything except NaNs (which are already in place). */ - doSort(a, left, n); + sort(a, left, right, true); /* - * Phase 3: Turn positive zeros back into negative zeros as appropriate + * Phase 3: Place negative zeros before positive zeros. */ - if (numNegativeZeros == 0) { - return; - } - - // Find first zero element - int zeroIndex = findAnyZero(a, left, n); - - for (int i = zeroIndex - 1; i >= left && a[i] == 0.0d; i--) { - zeroIndex = i; - } + int hi = right; - // Turn the right number of positive zeros back into negative zeros - for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) { - a[i] = -0.0d; - } - } - - /** - * Returns the index of some zero element in the specified range via - * binary search. The range is assumed to be sorted, and must contain - * at least one zero. - * - * @param a the array to be searched - * @param low the index of the first element, inclusive, to be searched - * @param high the index of the last element, inclusive, to be searched - */ - private static int findAnyZero(double[] a, int low, int high) { - while (true) { - int middle = (low + high) >>> 1; + /* + * Search first zero, or first positive, or last negative element. + */ + while (left < hi) { + int middle = (left + hi) >>> 1; double middleValue = a[middle]; if (middleValue < 0.0d) { - low = middle + 1; - } else if (middleValue > 0.0d) { - high = middle - 1; - } else { // middleValue == 0.0d - return middle; + left = middle + 1; + } else { + hi = middle; + } + } + + /* + * Skip the last negative value (if any) or all leading negative zeros. + */ + while (left <= right && Double.doubleToRawLongBits(a[left]) < 0) { + left++; + } + + /* + * Move negative zeros to the beginning of the sub-range. + * + * Partitioning: + * + * +---------------------------------------------------+ + * | < 0.0 | -0.0 | 0.0 | ? ( >= 0.0 ) | + * +---------------------------------------------------+ + * ^ ^ ^ + * | | | + * left p k + * + * Invariants: + * + * all in (*, left) < 0.0 + * all in [left, p) == -0.0 + * all in [p, k) == 0.0 + * all in [k, right] >= 0.0 + * + * Pointer k is the first index of ?-part. + */ + for (int k = left + 1, p = left; k <= right; k++) { + double ak = a[k]; + if (ak != 0.0d) { + break; + } + if (Double.doubleToRawLongBits(ak) < 0) { // ak is -0.0d + a[k] = 0.0d; + a[p++] = -0.0d; } } } /** - * Sorts the specified range of the array into ascending order. This - * method differs from the public {@code sort} method in three ways: - * {@code right} index is inclusive, it does no range checking on - * {@code left} or {@code right}, and it does not handle negative - * zeros or NaNs in the array. - * - * @param a the array to be sorted, which must not contain -0.0d and NaN - * @param left the index of the first element, inclusive, to be sorted - * @param right the index of the last element, inclusive, to be sorted - */ - private static void doSort(double[] a, int left, int right) { - // Use insertion sort on tiny arrays - if (right - left + 1 < INSERTION_SORT_THRESHOLD) { - for (int i = left + 1; i <= right; i++) { - double ai = a[i]; - int j; - for (j = i - 1; j >= left && ai < a[j]; j--) { - a[j + 1] = a[j]; - } - a[j + 1] = ai; - } - } else { // Use Dual-Pivot Quicksort on large arrays - dualPivotQuicksort(a, left, right); - } - } - - /** * Sorts the specified range of the array into ascending order by the - * Dual-Pivot Quicksort algorithm. + * Dual-Pivot Quicksort algorithm. This method differs from the public + * {@code sort} method in that the {@code right} index is inclusive, + * it does no range checking on {@code left} or {@code right}, and has + * boolean flag whether insertion sort with sentinel is used or not. * * @param a the array to be sorted * @param left the index of the first element, inclusive, to be sorted * @param right the index of the last element, inclusive, to be sorted + * @param leftmost indicates if the part is the most left in the range */ - private static void dualPivotQuicksort(double[] a, int left, int right) { - // Compute indices of five evenly spaced elements - int sixth = (right - left + 1) / 6; - int e1 = left + sixth; - int e5 = right - sixth; - int e3 = (left + right) >>> 1; // The midpoint - int e4 = e3 + sixth; - int e2 = e3 - sixth; + private static void sort(double[] a, int left,int right,boolean leftmost) { + int length = right - left + 1; - // Sort these elements using a 5-element sorting network - double ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5]; + // Use insertion sort on tiny arrays + if (length < INSERTION_SORT_THRESHOLD) { + if (!leftmost) { + /* + * Every element in adjoining part plays the role + * of sentinel, therefore this allows us to avoid + * the j >= left check on each iteration. + */ + for (int j, i = left + 1; i <= right; i++) { + double ai = a[i]; + for (j = i - 1; ai < a[j]; j--) { + // assert j >= left; + a[j + 1] = a[j]; + } + a[j + 1] = ai; + } + } else { + /* + * For case of leftmost part traditional (without a sentinel) + * insertion sort, optimized for server JVM, is used. + */ + for (int i = left, j = i; i < right; j = ++i) { + double ai = a[i + 1]; + while (ai < a[j]) { + a[j + 1] = a[j]; + if (j-- == left) { + break; + } + } + a[j + 1] = ai; + } + } + return; + } - if (ae1 > ae2) { double t = ae1; ae1 = ae2; ae2 = t; } - if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; } - if (ae1 > ae3) { double t = ae1; ae1 = ae3; ae3 = t; } - if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; } - if (ae1 > ae4) { double t = ae1; ae1 = ae4; ae4 = t; } - if (ae3 > ae4) { double t = ae3; ae3 = ae4; ae4 = t; } - if (ae2 > ae5) { double t = ae2; ae2 = ae5; ae5 = t; } - if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; } - if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; } + // Inexpensive approximation of length / 7 + int seventh = (length >>> 3) + (length >>> 6) + 1; + + /* + * Sort five evenly spaced elements around (and including) the + * center element in the range. These elements will be used for + * pivot selection as described below. The choice for spacing + * these elements was empirically determined to work well on + * a wide variety of inputs. + */ + int e3 = (left + right) >>> 1; // The midpoint + int e2 = e3 - seventh; + int e1 = e2 - seventh; + int e4 = e3 + seventh; + int e5 = e4 + seventh; - a[e1] = ae1; a[e3] = ae3; a[e5] = ae5; + // Sort these elements using insertion sort + if (a[e2] < a[e1]) { double t = a[e2]; a[e2] = a[e1]; a[e1] = t; } + + if (a[e3] < a[e2]) { double t = a[e3]; a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + if (a[e4] < a[e3]) { double t = a[e4]; a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + if (a[e5] < a[e4]) { double t = a[e5]; a[e5] = a[e4]; a[e4] = t; + if (t < a[e3]) { a[e4] = a[e3]; a[e3] = t; + if (t < a[e2]) { a[e3] = a[e2]; a[e2] = t; + if (t < a[e1]) { a[e2] = a[e1]; a[e1] = t; } + } + } + } /* * Use the second and fourth of the five sorted elements as pivots. * These values are inexpensive approximations of the first and * second terciles of the array. Note that pivot1 <= pivot2. - * - * The pivots are stored in local variables, and the first and - * the last of the elements to be sorted are moved to the locations - * formerly occupied by the pivots. When partitioning is complete, - * the pivots are swapped back into their final positions, and - * excluded from subsequent sorting. */ - double pivot1 = ae2; a[e2] = a[left]; - double pivot2 = ae4; a[e4] = a[right]; + double pivot1 = a[e2]; + double pivot2 = a[e4]; // Pointers - int less = left + 1; // The index of first element of center part - int great = right - 1; // The index before first element of right part + int less = left; // The index of the first element of center part + int great = right; // The index before the first element of right part - boolean pivotsDiffer = (pivot1 != pivot2); + if (pivot1 != pivot2) { + /* + * The first and the last elements to be sorted are moved to the + * locations formerly occupied by the pivots. When partitioning + * is complete, the pivots are swapped back into their final + * positions, and excluded from subsequent sorting. + */ + a[e2] = a[left]; + a[e4] = a[right]; - if (pivotsDiffer) { + /* + * Skip elements, which are less or greater than pivot values. + */ + while (a[++less] < pivot1); + while (a[--great] > pivot2); + /* * Partitioning: * - * left part center part right part - * +------------------------------------------------------------+ - * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | - * +------------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +--------------------------------------------------------------+ + * | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 | + * +--------------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -2101,16 +2541,14 @@ * pivot1 <= all in [less, k) <= pivot2 * all in (great, right) > pivot2 * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ outer: for (int k = less; k <= great; k++) { double ak = a[k]; if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; } else if (ak > pivot2) { // Move a[k] to right part while (a[great] > pivot2) { @@ -2120,26 +2558,107 @@ } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // pivot1 <= a[great] <= pivot2 a[k] = a[great]; - a[great--] = ak; + } + a[great] = ak; + great--; + } + } + + // Swap pivots into their final positions + a[left] = a[less - 1]; a[less - 1] = pivot1; + a[right] = a[great + 1]; a[great + 1] = pivot2; + + // Sort left and right parts recursively, excluding known pivots + sort(a, left, less - 2, leftmost); + sort(a, great + 2, right, false); + + /* + * If center part is too large (comprises > 5/7 of the array), + * swap internal pivot values to ends. + */ + if (less < e1 && e5 < great) { + /* + * Skip elements, which are equal to pivot values. + */ + while (a[less] == pivot1) { + less++; + } + while (a[great] == pivot2) { + great--; + } + + /* + * Partitioning: + * + * left part center part right part + * +----------------------------------------------------------+ + * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | + * +----------------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great + * + * Invariants: + * + * all in (*, less) == pivot1 + * pivot1 < all in [less, k) < pivot2 + * all in (great, *) == pivot2 + * + * Pointer k is the first index of ?-part. + */ + outer: + for (int k = less; k <= great; k++) { + double ak = a[k]; + if (ak == pivot1) { // Move a[k] to left part + a[k] = a[less]; + a[less] = ak; + less++; + } else if (ak == pivot2) { // Move a[k] to right part + while (a[great] == pivot2) { + if (great-- == k) { + break outer; + } + } + if (a[great] == pivot1) { + a[k] = a[less]; + /* + * Even though a[great] equals to pivot1, the + * assignment a[less] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point zeros + * of different signs. Therefore in float and + * double sorting methods we have to use more + * accurate assignment a[less] = a[great]. + */ + a[less] = a[great]; + less++; + } else { // pivot1 < a[great] < pivot2 + a[k] = a[great]; + } + a[great] = ak; + great--; } } } + + // Sort center part recursively + sort(a, less, great, false); + } else { // Pivots are equal /* - * Partition degenerates to the traditional 3-way, - * or "Dutch National Flag", partition: + * Partition degenerates to the traditional 3-way + * (or "Dutch National Flag") schema: * - * left part center part right part - * +----------------------------------------------+ - * | < pivot | == pivot | ? | > pivot | - * +----------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great + * left part center part right part + * +-------------------------------------------------+ + * | < pivot | == pivot | ? | > pivot | + * +-------------------------------------------------+ + * ^ ^ ^ + * | | | + * less k great * * Invariants: * @@ -2147,20 +2666,19 @@ * all in [less, k) == pivot * all in (great, right) > pivot * - * Pointer k is the first index of ?-part + * Pointer k is the first index of ?-part. */ - for (int k = less; k <= great; k++) { - double ak = a[k]; - if (ak == pivot1) { + for (int k = left; k <= great; k++) { + if (a[k] == pivot1) { continue; } + double ak = a[k]; + if (ak < pivot1) { // Move a[k] to left part - if (k != less) { - a[k] = a[less]; - a[less] = ak; - } + a[k] = a[less]; + a[less] = ak; less++; - } else { // (a[k] > pivot1) - Move a[k] to right part + } else { // a[k] > pivot1 - Move a[k] to right part /* * We know that pivot1 == a[e3] == pivot2. Thus, we know * that great will still be >= k when the following loop @@ -2168,102 +2686,43 @@ * In other words, a[e3] acts as a sentinel for great. */ while (a[great] > pivot1) { + // assert great > k; great--; } if (a[great] < pivot1) { a[k] = a[less]; - a[less++] = a[great]; - a[great--] = ak; + a[less] = a[great]; + less++; } else { // a[great] == pivot1 - a[k] = pivot1; - a[great--] = ak; + /* + * Even though a[great] equals to pivot1, the + * assignment a[k] = pivot1 may be incorrect, + * if a[great] and pivot1 are floating-point + * zeros of different signs. Therefore in float + * and double sorting methods we have to use + * more accurate assignment a[k] = a[great]. + */ + a[k] = a[great]; } + a[great] = ak; + great--; } } - } - - // Swap pivots into their final positions - a[left] = a[less - 1]; a[less - 1] = pivot1; - a[right] = a[great + 1]; a[great + 1] = pivot2; - - // Sort left and right parts recursively, excluding known pivot values - doSort(a, left, less - 2); - doSort(a, great + 2, right); - - /* - * If pivot1 == pivot2, all elements from center - * part are equal and, therefore, already sorted - */ - if (!pivotsDiffer) { - return; - } - - /* - * If center part is too large (comprises > 2/3 of the array), - * swap internal pivot values to ends - */ - if (less < e1 && great > e5) { - while (a[less] == pivot1) { - less++; - } - while (a[great] == pivot2) { - great--; - } - /* - * Partitioning: - * - * left part center part right part - * +----------------------------------------------------------+ - * | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 | - * +----------------------------------------------------------+ - * ^ ^ ^ - * | | | - * less k great - * - * Invariants: - * - * all in (*, less) == pivot1 - * pivot1 < all in [less, k) < pivot2 - * all in (great, *) == pivot2 - * - * Pointer k is the first index of ?-part - */ - outer: - for (int k = less; k <= great; k++) { - double ak = a[k]; - if (ak == pivot2) { // Move a[k] to right part - while (a[great] == pivot2) { - if (great-- == k) { - break outer; - } - } - if (a[great] == pivot1) { - a[k] = a[less]; - a[less++] = pivot1; - } else { // pivot1 < a[great] < pivot2 - a[k] = a[great]; - } - a[great--] = pivot2; - } else if (ak == pivot1) { // Move a[k] to left part - a[k] = a[less]; - a[less++] = pivot1; - } - } + // Sort left and right parts recursively + sort(a, left, less - 1, leftmost); + sort(a, great + 1, right, false); } - - // Sort center part recursively, excluding known pivot values - doSort(a, less, great); } /** - * Checks that {@code fromIndex} and {@code toIndex} are in - * the range and throws an appropriate exception, if they aren't. + * Checks that {@code fromIndex} and {@code toIndex} are in the range, + * otherwise throws an appropriate exception. */ private static void rangeCheck(int length, int fromIndex, int toIndex) { if (fromIndex > toIndex) { throw new IllegalArgumentException( - "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")"); + "fromIndex: " + fromIndex + " > toIndex: " + toIndex); } if (fromIndex < 0) { throw new ArrayIndexOutOfBoundsException(fromIndex);
--- a/src/share/classes/java/util/Scanner.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/util/Scanner.java Tue Jul 20 22:21:31 2010 -0700 @@ -343,7 +343,7 @@ * * @since 1.5 */ -public final class Scanner implements Iterator<String> { +public final class Scanner implements Iterator<String>, Closeable { // Internal buffer used to hold input private CharBuffer buf;
--- a/src/share/classes/java/util/logging/LogManager.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/util/logging/LogManager.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.io.*; import java.util.*; import java.security.*; +import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; @@ -154,10 +155,10 @@ = new PropertyChangeSupport(LogManager.class); private final static Level defaultLevel = Level.INFO; - // Table of known loggers. Maps names to Loggers. - private Hashtable<String,WeakReference<Logger>> loggers = - new Hashtable<String,WeakReference<Logger>>(); - // Tree of known loggers + // Table of named Loggers that maps names to Loggers. + private Hashtable<String,LoggerWeakRef> namedLoggers = + new Hashtable<String,LoggerWeakRef>(); + // Tree of named Loggers private LogNode root = new LogNode(null); private Logger rootLogger; @@ -417,6 +418,121 @@ }}); } + + // loggerRefQueue holds LoggerWeakRef objects for Logger objects + // that have been GC'ed. + private final ReferenceQueue<Logger> loggerRefQueue + = new ReferenceQueue<Logger>(); + + // Package-level inner class. + // Helper class for managing WeakReferences to Logger objects. + // + // LogManager.namedLoggers + // - has weak references to all named Loggers + // - namedLoggers keeps the LoggerWeakRef objects for the named + // Loggers around until we can deal with the book keeping for + // the named Logger that is being GC'ed. + // LogManager.LogNode.loggerRef + // - has a weak reference to a named Logger + // - the LogNode will also keep the LoggerWeakRef objects for + // the named Loggers around; currently LogNodes never go away. + // Logger.kids + // - has a weak reference to each direct child Logger; this + // includes anonymous and named Loggers + // - anonymous Loggers are always children of the rootLogger + // which is a strong reference; rootLogger.kids keeps the + // LoggerWeakRef objects for the anonymous Loggers around + // until we can deal with the book keeping. + // + final class LoggerWeakRef extends WeakReference<Logger> { + private String name; // for namedLoggers cleanup + private LogNode node; // for loggerRef cleanup + private WeakReference<Logger> parentRef; // for kids cleanup + + LoggerWeakRef(Logger logger) { + super(logger, loggerRefQueue); + + name = logger.getName(); // save for namedLoggers cleanup + } + + // dispose of this LoggerWeakRef object + void dispose() { + if (node != null) { + // if we have a LogNode, then we were a named Logger + // so clear namedLoggers weak ref to us + manager.namedLoggers.remove(name); + name = null; // clear our ref to the Logger's name + + node.loggerRef = null; // clear LogNode's weak ref to us + node = null; // clear our ref to LogNode + } + + if (parentRef != null) { + // this LoggerWeakRef has or had a parent Logger + Logger parent = parentRef.get(); + if (parent != null) { + // the parent Logger is still there so clear the + // parent Logger's weak ref to us + parent.removeChildLogger(this); + } + parentRef = null; // clear our weak ref to the parent Logger + } + } + + // set the node field to the specified value + void setNode(LogNode node) { + this.node = node; + } + + // set the parentRef field to the specified value + void setParentRef(WeakReference<Logger> parentRef) { + this.parentRef = parentRef; + } + } + + // Package-level method. + // Drain some Logger objects that have been GC'ed. + // + // drainLoggerRefQueueBounded() is called by addLogger() below + // and by Logger.getAnonymousLogger(String) so we'll drain up to + // MAX_ITERATIONS GC'ed Loggers for every Logger we add. + // + // On a WinXP VMware client, a MAX_ITERATIONS value of 400 gives + // us about a 50/50 mix in increased weak ref counts versus + // decreased weak ref counts in the AnonLoggerWeakRefLeak test. + // Here are stats for cleaning up sets of 400 anonymous Loggers: + // - test duration 1 minute + // - sample size of 125 sets of 400 + // - average: 1.99 ms + // - minimum: 0.57 ms + // - maximum: 25.3 ms + // + // The same config gives us a better decreased weak ref count + // than increased weak ref count in the LoggerWeakRefLeak test. + // Here are stats for cleaning up sets of 400 named Loggers: + // - test duration 2 minutes + // - sample size of 506 sets of 400 + // - average: 0.57 ms + // - minimum: 0.02 ms + // - maximum: 10.9 ms + // + private final static int MAX_ITERATIONS = 400; + final synchronized void drainLoggerRefQueueBounded() { + for (int i = 0; i < MAX_ITERATIONS; i++) { + if (loggerRefQueue == null) { + // haven't finished loading LogManager yet + break; + } + + LoggerWeakRef ref = (LoggerWeakRef) loggerRefQueue.poll(); + if (ref == null) { + break; + } + // a Logger object has been GC'ed so clean it up + ref.dispose(); + } + } + /** * Add a named logger. This does nothing and returns false if a logger * with the same name is already registered. @@ -439,13 +555,16 @@ throw new NullPointerException(); } - WeakReference<Logger> ref = loggers.get(name); + // cleanup some Loggers that have been GC'ed + drainLoggerRefQueueBounded(); + + LoggerWeakRef ref = namedLoggers.get(name); if (ref != null) { if (ref.get() == null) { - // Hashtable holds stale weak reference - // to a logger which has been GC-ed. - // Allow to register new one. - loggers.remove(name); + // It's possible that the Logger was GC'ed after the + // drainLoggerRefQueueBounded() call above so allow + // a new one to be registered. + namedLoggers.remove(name); } else { // We already have a registered logger with the given name. return false; @@ -454,7 +573,8 @@ // We're adding a new logger. // Note that we are creating a weak reference here. - loggers.put(name, new WeakReference<Logger>(logger)); + ref = new LoggerWeakRef(logger); + namedLoggers.put(name, ref); // Apply any initial level defined for the new logger. Level level = getLevelProperty(name+".level", null); @@ -469,11 +589,11 @@ // Find the new node and its parent. LogNode node = findNode(name); - node.loggerRef = new WeakReference<Logger>(logger); + node.loggerRef = ref; Logger parent = null; LogNode nodep = node.parent; while (nodep != null) { - WeakReference<Logger> nodeRef = nodep.loggerRef; + LoggerWeakRef nodeRef = nodep.loggerRef; if (nodeRef != null) { parent = nodeRef.get(); if (parent != null) { @@ -489,6 +609,9 @@ // Walk over the children and tell them we are their new parent. node.walkAndSetParent(logger); + // new LogNode is ready so tell the LoggerWeakRef about it + ref.setNode(node); + return true; } @@ -572,7 +695,7 @@ * @return matching logger or null if none is found */ public synchronized Logger getLogger(String name) { - WeakReference<Logger> ref = loggers.get(name); + LoggerWeakRef ref = namedLoggers.get(name); if (ref == null) { return null; } @@ -580,7 +703,7 @@ if (logger == null) { // Hashtable holds stale weak reference // to a logger which has been GC-ed. - loggers.remove(name); + namedLoggers.remove(name); } return logger; } @@ -594,7 +717,7 @@ * @return enumeration of logger name strings */ public synchronized Enumeration<String> getLoggerNames() { - return loggers.keys(); + return namedLoggers.keys(); } /** @@ -942,7 +1065,7 @@ // Nested class to represent a node in our tree of named loggers. private static class LogNode { HashMap<String,LogNode> children; - WeakReference<Logger> loggerRef; + LoggerWeakRef loggerRef; LogNode parent; LogNode(LogNode parent) { @@ -958,7 +1081,7 @@ Iterator<LogNode> values = children.values().iterator(); while (values.hasNext()) { LogNode node = values.next(); - WeakReference<Logger> ref = node.loggerRef; + LoggerWeakRef ref = node.loggerRef; Logger logger = (ref == null) ? null : ref.get(); if (logger == null) { node.walkAndSetParent(parent);
--- a/src/share/classes/java/util/logging/Logger.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/java/util/logging/Logger.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -183,7 +183,7 @@ // We keep weak references from parents to children, but strong // references from children to parents. private volatile Logger parent; // our nearest parent. - private ArrayList<WeakReference<Logger>> kids; // WeakReferences to loggers that have us as parent + private ArrayList<LogManager.LoggerWeakRef> kids; // WeakReferences to loggers that have us as parent private volatile Level levelObject; private volatile int levelValue; // current effective level value @@ -366,13 +366,8 @@ * * @return a newly created private Logger */ - public static synchronized Logger getAnonymousLogger() { - LogManager manager = LogManager.getLogManager(); - Logger result = new Logger(null, null); - result.anonymous = true; - Logger root = manager.getLogger(""); - result.doSetParent(root); - return result; + public static Logger getAnonymousLogger() { + return getAnonymousLogger(null); } /** @@ -401,6 +396,8 @@ */ public static synchronized Logger getAnonymousLogger(String resourceBundleName) { LogManager manager = LogManager.getLogManager(); + // cleanup some Loggers that have been GC'ed + manager.drainLoggerRefQueueBounded(); Logger result = new Logger(null, resourceBundleName); result.anonymous = true; Logger root = manager.getLogger(""); @@ -1380,14 +1377,18 @@ synchronized (treeLock) { // Remove ourself from any previous parent. + LogManager.LoggerWeakRef ref = null; if (parent != null) { // assert parent.kids != null; - for (Iterator<WeakReference<Logger>> iter = parent.kids.iterator(); iter.hasNext(); ) { - WeakReference<Logger> ref = iter.next(); + for (Iterator<LogManager.LoggerWeakRef> iter = parent.kids.iterator(); iter.hasNext(); ) { + ref = iter.next(); Logger kid = ref.get(); if (kid == this) { + // ref is used down below to complete the reparenting iter.remove(); break; + } else { + ref = null; } } // We have now removed ourself from our parents' kids. @@ -1396,9 +1397,14 @@ // Set our new parent. parent = newParent; if (parent.kids == null) { - parent.kids = new ArrayList<WeakReference<Logger>>(2); + parent.kids = new ArrayList<LogManager.LoggerWeakRef>(2); } - parent.kids.add(new WeakReference<Logger>(this)); + if (ref == null) { + // we didn't have a previous parent + ref = manager.new LoggerWeakRef(this); + } + ref.setParentRef(new WeakReference<Logger>(parent)); + parent.kids.add(ref); // As a result of the reparenting, the effective level // may have changed for us and our children. @@ -1407,6 +1413,21 @@ } } + // Package-level method. + // Remove the weak reference for the specified child Logger from the + // kid list. We should only be called from LoggerWeakRef.dispose(). + final void removeChildLogger(LogManager.LoggerWeakRef child) { + synchronized (treeLock) { + for (Iterator<LogManager.LoggerWeakRef> iter = kids.iterator(); iter.hasNext(); ) { + LogManager.LoggerWeakRef ref = iter.next(); + if (ref == child) { + iter.remove(); + return; + } + } + } + } + // Recalculate the effective level for this node and // recursively for our children. @@ -1438,7 +1459,7 @@ // Recursively update the level on each of our kids. if (kids != null) { for (int i = 0; i < kids.size(); i++) { - WeakReference<Logger> ref = kids.get(i); + LogManager.LoggerWeakRef ref = kids.get(i); Logger kid = ref.get(); if (kid != null) { kid.updateEffectiveLevel();
--- a/src/share/classes/javax/imageio/stream/ImageInputStream.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/imageio/stream/ImageInputStream.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,6 +25,7 @@ package javax.imageio.stream; +import java.io.Closeable; import java.io.DataInput; import java.io.IOException; import java.nio.ByteOrder; @@ -42,7 +43,7 @@ * @see MemoryCacheImageInputStream * */ -public interface ImageInputStream extends DataInput { +public interface ImageInputStream extends DataInput, Closeable { /** * Sets the desired byte order for future reads of data values
--- a/src/share/classes/javax/sound/midi/MidiDevice.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/sound/midi/MidiDevice.java Tue Jul 20 22:21:31 2010 -0700 @@ -107,7 +107,7 @@ * @author Florian Bomers */ -public interface MidiDevice { +public interface MidiDevice extends AutoCloseable { /**
--- a/src/share/classes/javax/sound/midi/Receiver.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/sound/midi/Receiver.java Tue Jul 20 22:21:31 2010 -0700 @@ -38,7 +38,7 @@ * * @author Kara Kytle */ -public interface Receiver { +public interface Receiver extends AutoCloseable { //$$fb 2002-04-12: fix for 4662090: Contradiction in Receiver specification
--- a/src/share/classes/javax/sound/midi/Transmitter.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/sound/midi/Transmitter.java Tue Jul 20 22:21:31 2010 -0700 @@ -35,7 +35,7 @@ * * @author Kara Kytle */ -public interface Transmitter { +public interface Transmitter extends AutoCloseable { /**
--- a/src/share/classes/javax/sound/sampled/Line.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/sound/sampled/Line.java Tue Jul 20 22:21:31 2010 -0700 @@ -70,7 +70,7 @@ * @see LineEvent * @since 1.3 */ -public interface Line { +public interface Line extends AutoCloseable { /** * Obtains the <code>Line.Info</code> object describing this
--- a/src/share/classes/javax/swing/JSplitPane.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/JSplitPane.java Tue Jul 20 22:21:31 2010 -0700 @@ -242,19 +242,19 @@ /** * Creates a new <code>JSplitPane</code> configured to arrange the child - * components side-by-side horizontally with no continuous - * layout, using two buttons for the components. + * components side-by-side horizontally, using two buttons for the components. */ public JSplitPane() { - this(JSplitPane.HORIZONTAL_SPLIT, false, - new JButton(UIManager.getString("SplitPane.leftButtonText")), - new JButton(UIManager.getString("SplitPane.rightButtonText"))); + this(JSplitPane.HORIZONTAL_SPLIT, + UIManager.getBoolean("SplitPane.continuousLayout"), + new JButton(UIManager.getString("SplitPane.leftButtonText")), + new JButton(UIManager.getString("SplitPane.rightButtonText"))); } /** * Creates a new <code>JSplitPane</code> configured with the - * specified orientation and no continuous layout. + * specified orientation. * * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or * <code>JSplitPane.VERTICAL_SPLIT</code> @@ -263,7 +263,8 @@ */ @ConstructorProperties({"orientation"}) public JSplitPane(int newOrientation) { - this(newOrientation, false); + this(newOrientation, + UIManager.getBoolean("SplitPane.continuousLayout")); } @@ -287,9 +288,7 @@ /** * Creates a new <code>JSplitPane</code> with the specified - * orientation and - * with the specified components that do not do continuous - * redrawing. + * orientation and the specified components. * * @param newOrientation <code>JSplitPane.HORIZONTAL_SPLIT</code> or * <code>JSplitPane.VERTICAL_SPLIT</code> @@ -307,7 +306,9 @@ public JSplitPane(int newOrientation, Component newLeftComponent, Component newRightComponent){ - this(newOrientation, false, newLeftComponent, newRightComponent); + this(newOrientation, + UIManager.getBoolean("SplitPane.continuousLayout"), + newLeftComponent, newRightComponent); }
--- a/src/share/classes/javax/swing/JTable.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/JTable.java Tue Jul 20 22:21:31 2010 -0700 @@ -1048,7 +1048,7 @@ /** * Returns the horizontal and vertical space between cells. - * The default spacing is (1, 1), which provides room to draw the grid. + * The default spacing is look and feel dependent. * * @return the horizontal and vertical spacing between cells * @see #setIntercellSpacing @@ -1155,7 +1155,7 @@ /** * Returns true if the table draws horizontal lines between cells, false if it - * doesn't. The default is true. + * doesn't. The default value is look and feel dependent. * * @return true if the table draws horizontal lines between cells, false if it * doesn't @@ -1167,7 +1167,7 @@ /** * Returns true if the table draws vertical lines between cells, false if it - * doesn't. The default is true. + * doesn't. The default value is look and feel dependent. * * @return true if the table draws vertical lines between cells, false if it * doesn't
--- a/src/share/classes/javax/swing/JTree.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/JTree.java Tue Jul 20 22:21:31 2010 -0700 @@ -1986,20 +1986,17 @@ * true if all nodes in the path are expanded */ public boolean isExpanded(TreePath path) { + if(path == null) return false; - - // Is this node expanded? - Boolean value = expandedState.get(path); - - if(value == null || !value.booleanValue()) - return false; - - // It is, make sure its parent is also expanded. - TreePath parentPath = path.getParentPath(); - - if(parentPath != null) - return isExpanded(parentPath); + Object value; + + do{ + value = expandedState.get(path); + if(value == null || !((Boolean)value).booleanValue()) + return false; + } while( (path=path.getParentPath())!=null ); + return true; }
--- a/src/share/classes/javax/swing/border/TitledBorder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/border/TitledBorder.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,22 +24,20 @@ */ package javax.swing.border; -import sun.swing.SwingUtilities2; - +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; -import java.awt.Color; -import java.awt.Font; -import java.awt.FontMetrics; -import java.awt.Point; -import java.awt.Toolkit; -import java.awt.Component; -import java.awt.Dimension; +import java.awt.geom.Path2D; import java.beans.ConstructorProperties; - import javax.swing.JComponent; +import javax.swing.JLabel; import javax.swing.UIManager; +import javax.swing.plaf.basic.BasicHTML; /** * A class which implements an arbitrary border @@ -73,40 +71,40 @@ { protected String title; protected Border border; - protected int titlePosition; - protected int titleJustification; - protected Font titleFont; - protected Color titleColor; + protected int titlePosition; + protected int titleJustification; + protected Font titleFont; + protected Color titleColor; - private Point textLoc = new Point(); + private final JLabel label; /** * Use the default vertical orientation for the title text. */ static public final int DEFAULT_POSITION = 0; /** Position the title above the border's top line. */ - static public final int ABOVE_TOP = 1; + static public final int ABOVE_TOP = 1; /** Position the title in the middle of the border's top line. */ - static public final int TOP = 2; + static public final int TOP = 2; /** Position the title below the border's top line. */ - static public final int BELOW_TOP = 3; + static public final int BELOW_TOP = 3; /** Position the title above the border's bottom line. */ - static public final int ABOVE_BOTTOM = 4; + static public final int ABOVE_BOTTOM = 4; /** Position the title in the middle of the border's bottom line. */ - static public final int BOTTOM = 5; + static public final int BOTTOM = 5; /** Position the title below the border's bottom line. */ - static public final int BELOW_BOTTOM = 6; + static public final int BELOW_BOTTOM = 6; /** * Use the default justification for the title text. */ static public final int DEFAULT_JUSTIFICATION = 0; /** Position title text at the left side of the border line. */ - static public final int LEFT = 1; + static public final int LEFT = 1; /** Position title text in the center of the border line. */ - static public final int CENTER = 2; + static public final int CENTER = 2; /** Position title text at the right side of the border line. */ - static public final int RIGHT = 3; + static public final int RIGHT = 3; /** Position title text at the left side of the border line * for left to right orientation, at the right side of the * border line for right to left orientation. @@ -132,7 +130,7 @@ * * @param title the title the border should display */ - public TitledBorder(String title) { + public TitledBorder(String title) { this(null, title, LEADING, DEFAULT_POSITION, null, null); } @@ -142,7 +140,7 @@ * * @param border the border */ - public TitledBorder(Border border) { + public TitledBorder(Border border) { this(border, "", LEADING, DEFAULT_POSITION, null, null); } @@ -167,9 +165,9 @@ * @param titlePosition the position for the title */ public TitledBorder(Border border, - String title, - int titleJustification, - int titlePosition) { + String title, + int titleJustification, + int titlePosition) { this(border, title, titleJustification, titlePosition, null, null); } @@ -185,10 +183,10 @@ * @param titleFont the font for rendering the title */ public TitledBorder(Border border, - String title, - int titleJustification, - int titlePosition, - Font titleFont) { + String title, + int titleJustification, + int titlePosition, + Font titleFont) { this(border, title, titleJustification, titlePosition, titleFont, null); } @@ -207,11 +205,11 @@ */ @ConstructorProperties({"border", "title", "titleJustification", "titlePosition", "titleFont", "titleColor"}) public TitledBorder(Border border, - String title, - int titleJustification, - int titlePosition, - Font titleFont, - Color titleColor) { + String title, + int titleJustification, + int titlePosition, + Font titleFont, + Color titleColor) { this.title = title; this.border = border; this.titleFont = titleFont; @@ -219,6 +217,10 @@ setTitleJustification(titleJustification); setTitlePosition(titlePosition); + + this.label = new JLabel(); + this.label.setOpaque(false); + this.label.putClientProperty(BasicHTML.propertyKey, null); } /** @@ -232,178 +234,111 @@ * @param height the height of the painted border */ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { - - Border border = getBorder(); - - if (getTitle() == null || getTitle().equals("")) { - if (border != null) { - border.paintBorder(c, g, x, y, width, height); - } - return; - } - - Rectangle grooveRect = new Rectangle(x + EDGE_SPACING, y + EDGE_SPACING, - width - (EDGE_SPACING * 2), - height - (EDGE_SPACING * 2)); - Font font = g.getFont(); - Color color = g.getColor(); + Border border = getBorderUI(); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = (border != null) + ? border.getBorderInsets(c) + : new Insets(0, 0, 0, 0); - g.setFont(getFont(c)); - - JComponent jc = (c instanceof JComponent) ? (JComponent)c : null; - FontMetrics fm = SwingUtilities2.getFontMetrics(jc, g); - int fontHeight = fm.getHeight(); - int descent = fm.getDescent(); - int ascent = fm.getAscent(); - int diff; - int stringWidth = SwingUtilities2.stringWidth(jc, fm, - getTitle()); - Insets insets; - - if (border != null) { - insets = border.getBorderInsets(c); - } else { - insets = new Insets(0, 0, 0, 0); - } + int borderX = x + edge; + int borderY = y + edge; + int borderW = width - edge - edge; + int borderH = height - edge - edge; - int titlePos = getTitlePosition(); - switch (titlePos) { - case ABOVE_TOP: - diff = ascent + descent + (Math.max(EDGE_SPACING, - TEXT_SPACING*2) - EDGE_SPACING); - grooveRect.y += diff; - grooveRect.height -= diff; - textLoc.y = grooveRect.y - (descent + TEXT_SPACING); - break; - case TOP: - case DEFAULT_POSITION: - diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - EDGE_SPACING); - grooveRect.y += diff; - grooveRect.height -= diff; - textLoc.y = (grooveRect.y - descent) + - (insets.top + ascent + descent)/2; - break; - case BELOW_TOP: - textLoc.y = grooveRect.y + insets.top + ascent + TEXT_SPACING; - break; - case ABOVE_BOTTOM: - textLoc.y = (grooveRect.y + grooveRect.height) - - (insets.bottom + descent + TEXT_SPACING); - break; - case BOTTOM: - grooveRect.height -= fontHeight/2; - textLoc.y = ((grooveRect.y + grooveRect.height) - descent) + - ((ascent + descent) - insets.bottom)/2; - break; - case BELOW_BOTTOM: - grooveRect.height -= fontHeight; - textLoc.y = grooveRect.y + grooveRect.height + ascent + - TEXT_SPACING; - break; - } - - int justification = getTitleJustification(); - if(isLeftToRight(c)) { - if(justification==LEADING || - justification==DEFAULT_JUSTIFICATION) { - justification = LEFT; - } - else if(justification==TRAILING) { - justification = RIGHT; - } - } - else { - if(justification==LEADING || - justification==DEFAULT_JUSTIFICATION) { - justification = RIGHT; + int labelY = y; + int labelH = size.height; + int position = getPosition(); + switch (position) { + case ABOVE_TOP: + insets.left = 0; + insets.right = 0; + borderY += labelH - edge; + borderH -= labelH - edge; + break; + case TOP: + insets.top = edge + insets.top/2 - labelH/2; + if (insets.top < edge) { + borderY -= insets.top; + borderH += insets.top; + } + else { + labelY += insets.top; + } + break; + case BELOW_TOP: + labelY += insets.top + edge; + break; + case ABOVE_BOTTOM: + labelY += height - labelH - insets.bottom - edge; + break; + case BOTTOM: + labelY += height - labelH; + insets.bottom = edge + (insets.bottom - labelH) / 2; + if (insets.bottom < edge) { + borderH += insets.bottom; + } + else { + labelY -= insets.bottom; + } + break; + case BELOW_BOTTOM: + insets.left = 0; + insets.right = 0; + labelY += height - labelH; + borderH -= labelH - edge; + break; } - else if(justification==TRAILING) { - justification = LEFT; - } - } - - switch (justification) { - case LEFT: - textLoc.x = grooveRect.x + TEXT_INSET_H + insets.left; - break; - case RIGHT: - textLoc.x = (grooveRect.x + grooveRect.width) - - (stringWidth + TEXT_INSET_H + insets.right); - break; - case CENTER: - textLoc.x = grooveRect.x + - ((grooveRect.width - stringWidth) / 2); - break; - } + insets.left += edge + TEXT_INSET_H; + insets.right += edge + TEXT_INSET_H; - // If title is positioned in middle of border AND its fontsize - // is greater than the border's thickness, we'll need to paint - // the border in sections to leave space for the component's background - // to show through the title. - // - if (border != null) { - if (((titlePos == TOP || titlePos == DEFAULT_POSITION) && - (grooveRect.y > textLoc.y - ascent)) || - (titlePos == BOTTOM && - (grooveRect.y + grooveRect.height < textLoc.y + descent))) { - - Rectangle clipRect = new Rectangle(); - - // save original clip - Rectangle saveClip = g.getClipBounds(); - - // paint strip left of text - clipRect.setBounds(saveClip); - if (computeIntersection(clipRect, x, y, textLoc.x-1-x, height)) { - g.setClip(clipRect); - border.paintBorder(c, g, grooveRect.x, grooveRect.y, - grooveRect.width, grooveRect.height); - } + int labelX = x; + int labelW = width - insets.left - insets.right; + if (labelW > size.width) { + labelW = size.width; + } + switch (getJustification(c)) { + case LEFT: + labelX += insets.left; + break; + case RIGHT: + labelX += width - insets.right - labelW; + break; + case CENTER: + labelX += (width - labelW) / 2; + break; + } - // paint strip right of text - clipRect.setBounds(saveClip); - if (computeIntersection(clipRect, textLoc.x+stringWidth+1, y, - x+width-(textLoc.x+stringWidth+1), height)) { - g.setClip(clipRect); - border.paintBorder(c, g, grooveRect.x, grooveRect.y, - grooveRect.width, grooveRect.height); + if (border != null) { + if ((position != TOP) && (position != BOTTOM)) { + border.paintBorder(c, g, borderX, borderY, borderW, borderH); } - - if (titlePos == TOP || titlePos == DEFAULT_POSITION) { - // paint strip below text - clipRect.setBounds(saveClip); - if (computeIntersection(clipRect, textLoc.x-1, textLoc.y+descent, - stringWidth+2, y+height-textLoc.y-descent)) { - g.setClip(clipRect); - border.paintBorder(c, g, grooveRect.x, grooveRect.y, - grooveRect.width, grooveRect.height); + else { + Graphics g2 = g.create(); + if (g2 instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g2; + Path2D path = new Path2D.Float(); + path.append(new Rectangle(borderX, borderY, borderW, labelY - borderY), false); + path.append(new Rectangle(borderX, labelY, labelX - borderX - TEXT_SPACING, labelH), false); + path.append(new Rectangle(labelX + labelW + TEXT_SPACING, labelY, borderX - labelX + borderW - labelW - TEXT_SPACING, labelH), false); + path.append(new Rectangle(borderX, labelY + labelH, borderW, borderY - labelY + borderH - labelH), false); + g2d.clip(path); } - - } else { // titlePos == BOTTOM - // paint strip above text - clipRect.setBounds(saveClip); - if (computeIntersection(clipRect, textLoc.x-1, y, - stringWidth+2, textLoc.y - ascent - y)) { - g.setClip(clipRect); - border.paintBorder(c, g, grooveRect.x, grooveRect.y, - grooveRect.width, grooveRect.height); - } + border.paintBorder(c, g2, borderX, borderY, borderW, borderH); + g2.dispose(); } - - // restore clip - g.setClip(saveClip); - - } else { - border.paintBorder(c, g, grooveRect.x, grooveRect.y, - grooveRect.width, grooveRect.height); } + g.translate(labelX, labelY); + label.setSize(labelW, labelH); + label.paint(g); + g.translate(-labelX, -labelY); } - - g.setColor(getTitleColor()); - SwingUtilities2.drawString(jc, g, getTitle(), textLoc.x, textLoc.y); - - g.setFont(font); - g.setColor(color); + else if (border != null) { + border.paintBorder(c, g, x, y, width, height); + } } /** @@ -412,69 +347,54 @@ * @param insets the object to be reinitialized */ public Insets getBorderInsets(Component c, Insets insets) { - FontMetrics fm; - int descent = 0; - int ascent = 16; - int height = 16; - - Border border = getBorder(); - if (border != null) { - if (border instanceof AbstractBorder) { - ((AbstractBorder)border).getBorderInsets(c, insets); - } else { - // Can't reuse border insets because the Border interface - // can't be enhanced. - Insets i = border.getBorderInsets(c); - insets.top = i.top; - insets.right = i.right; - insets.bottom = i.bottom; - insets.left = i.left; - } - } else { - insets.left = insets.top = insets.right = insets.bottom = 0; + Border border = getBorderUI(); + if (border == null) { + insets.set(0, 0, 0, 0); + } + else if (border instanceof AbstractBorder) { + AbstractBorder ab = (AbstractBorder) border; + insets = ab.getBorderInsets(c, insets); } - - insets.left += EDGE_SPACING + TEXT_SPACING; - insets.right += EDGE_SPACING + TEXT_SPACING; - insets.top += EDGE_SPACING + TEXT_SPACING; - insets.bottom += EDGE_SPACING + TEXT_SPACING; - - if(c == null || getTitle() == null || getTitle().equals("")) { - return insets; + else { + Insets i = border.getBorderInsets(c); + insets.set(i.top, i.left, i.bottom, i.right); } + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); - Font font = getFont(c); - - fm = c.getFontMetrics(font); - - if(fm != null) { - descent = fm.getDescent(); - ascent = fm.getAscent(); - height = fm.getHeight(); - } - - switch (getTitlePosition()) { - case ABOVE_TOP: - insets.top += ascent + descent - + (Math.max(EDGE_SPACING, TEXT_SPACING*2) - - EDGE_SPACING); - break; - case TOP: - case DEFAULT_POSITION: - insets.top += ascent + descent; - break; - case BELOW_TOP: - insets.top += ascent + descent + TEXT_SPACING; - break; - case ABOVE_BOTTOM: - insets.bottom += ascent + descent + TEXT_SPACING; - break; - case BOTTOM: - insets.bottom += ascent + descent; - break; - case BELOW_BOTTOM: - insets.bottom += height; - break; + switch (getPosition()) { + case ABOVE_TOP: + insets.top += size.height - edge; + break; + case TOP: { + if (insets.top < size.height) { + insets.top = size.height - edge; + } + break; + } + case BELOW_TOP: + insets.top += size.height; + break; + case ABOVE_BOTTOM: + insets.bottom += size.height; + break; + case BOTTOM: { + if (insets.bottom < size.height) { + insets.bottom = size.height - edge; + } + break; + } + case BELOW_BOTTOM: + insets.bottom += size.height - edge; + break; + } + insets.top += edge + TEXT_SPACING; + insets.left += edge + TEXT_SPACING; + insets.right += edge + TEXT_SPACING; + insets.bottom += edge + TEXT_SPACING; } return insets; } @@ -492,41 +412,14 @@ /** * Returns the border of the titled border. */ - public Border getBorder() { - Border b = border; - if (b == null) - b = UIManager.getBorder("TitledBorder.border"); - return b; + public Border getBorder() { + return border; } /** * Returns the title-position of the titled border. */ public int getTitlePosition() { - if (titlePosition == DEFAULT_POSITION) { - Object value = UIManager.get("TitledBorder.position"); - if (value instanceof String) { - String s = (String)value; - if ("ABOVE_TOP".equalsIgnoreCase(s)) { - return ABOVE_TOP; - } else if ("TOP".equalsIgnoreCase(s)) { - return TOP; - } else if ("BELOW_TOP".equalsIgnoreCase(s)) { - return BELOW_TOP; - } else if ("ABOVE_BOTTOM".equalsIgnoreCase(s)) { - return ABOVE_BOTTOM; - } else if ("BOTTOM".equalsIgnoreCase(s)) { - return BOTTOM; - } else if ("BELOW_BOTTOM".equalsIgnoreCase(s)) { - return BELOW_BOTTOM; - } - } else if (value instanceof Integer) { - int i = (Integer)value; - if (i >= 0 && i <= 6) { - return i; - } - } - } return titlePosition; } @@ -539,20 +432,14 @@ * Returns the title-font of the titled border. */ public Font getTitleFont() { - Font f = titleFont; - if (f == null) - f = UIManager.getFont("TitledBorder.font"); - return f; + return titleFont; } /** * Returns the title-color of the titled border. */ public Color getTitleColor() { - Color c = titleColor; - if (c == null) - c = UIManager.getColor("TitledBorder.titleColor"); - return c; + return titleColor; } @@ -576,18 +463,18 @@ */ public void setTitlePosition(int titlePosition) { switch (titlePosition) { - case ABOVE_TOP: - case TOP: - case BELOW_TOP: - case ABOVE_BOTTOM: - case BOTTOM: - case BELOW_BOTTOM: - case DEFAULT_POSITION: + case ABOVE_TOP: + case TOP: + case BELOW_TOP: + case ABOVE_BOTTOM: + case BOTTOM: + case BELOW_BOTTOM: + case DEFAULT_POSITION: this.titlePosition = titlePosition; break; - default: - throw new IllegalArgumentException(titlePosition + - " is not a valid title position."); + default: + throw new IllegalArgumentException(titlePosition + + " is not a valid title position."); } } @@ -624,7 +511,7 @@ * @param titleColor the color for the border title */ public void setTitleColor(Color titleColor) { - this.titleColor = titleColor; + this.titleColor = titleColor; } /** @@ -636,22 +523,18 @@ Insets insets = getBorderInsets(c); Dimension minSize = new Dimension(insets.right+insets.left, insets.top+insets.bottom); - Font font = getFont(c); - FontMetrics fm = c.getFontMetrics(font); - JComponent jc = (c instanceof JComponent) ? (JComponent)c : null; - switch (getTitlePosition()) { - case ABOVE_TOP: - case BELOW_BOTTOM: - minSize.width = Math.max(SwingUtilities2.stringWidth(jc, fm, - getTitle()), minSize.width); - break; - case BELOW_TOP: - case ABOVE_BOTTOM: - case TOP: - case BOTTOM: - case DEFAULT_POSITION: - default: - minSize.width += SwingUtilities2.stringWidth(jc, fm, getTitle()); + String title = getTitle(); + if ((title != null) && !title.isEmpty()) { + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + + int position = getPosition(); + if ((position != ABOVE_TOP) && (position != BELOW_BOTTOM)) { + minSize.width += size.width; + } + else if (minSize.width < size.width) { + minSize.width += size.width; + } } return minSize; } @@ -674,48 +557,36 @@ if (height < 0) { throw new IllegalArgumentException("Height must be >= 0"); } + Border border = getBorderUI(); String title = getTitle(); - if (title != null && !"".equals(title)) { - Font font = getFont(c); - Border border2 = getBorder(); - Insets borderInsets; - if (border2 != null) { - borderInsets = border2.getBorderInsets(c); - } - else { - borderInsets = new Insets(0, 0, 0, 0); - } - FontMetrics fm = c.getFontMetrics(font); - int fontHeight = fm.getHeight(); - int descent = fm.getDescent(); - int ascent = fm.getAscent(); - int y = EDGE_SPACING; - int h = height - EDGE_SPACING * 2; - int diff; - switch (getTitlePosition()) { - case ABOVE_TOP: - diff = ascent + descent + (Math.max(EDGE_SPACING, - TEXT_SPACING * 2) - - EDGE_SPACING); - return y + diff - (descent + TEXT_SPACING); - case TOP: - case DEFAULT_POSITION: - diff = Math.max(0, ((ascent/2) + TEXT_SPACING) - - EDGE_SPACING); - return (y + diff - descent) + - (borderInsets.top + ascent + descent)/2; - case BELOW_TOP: - return y + borderInsets.top + ascent + TEXT_SPACING; - case ABOVE_BOTTOM: - return (y + h) - (borderInsets.bottom + descent + - TEXT_SPACING); - case BOTTOM: - h -= fontHeight / 2; - return ((y + h) - descent) + - ((ascent + descent) - borderInsets.bottom)/2; - case BELOW_BOTTOM: - h -= fontHeight; - return y + h + ascent + TEXT_SPACING; + if ((title != null) && !title.isEmpty()) { + int edge = (border instanceof TitledBorder) ? 0 : EDGE_SPACING; + JLabel label = getLabel(c); + Dimension size = label.getPreferredSize(); + Insets insets = (border != null) + ? border.getBorderInsets(c) + : new Insets(0, 0, 0, 0); + + int baseline = label.getBaseline(size.width, size.height); + switch (getPosition()) { + case ABOVE_TOP: + return baseline; + case TOP: + insets.top = edge + (insets.top - size.height) / 2; + return (insets.top < edge) + ? baseline + : baseline + insets.top; + case BELOW_TOP: + return baseline + insets.top + edge; + case ABOVE_BOTTOM: + return baseline + height - size.height - insets.bottom - edge; + case BOTTOM: + insets.bottom = edge + (insets.bottom - size.height) / 2; + return (insets.bottom < edge) + ? baseline + height - size.height + : baseline + height - size.height + insets.bottom; + case BELOW_BOTTOM: + return baseline + height - size.height; } } return -1; @@ -732,44 +603,111 @@ public Component.BaselineResizeBehavior getBaselineResizeBehavior( Component c) { super.getBaselineResizeBehavior(c); - switch(getTitlePosition()) { - case TitledBorder.ABOVE_TOP: - case TitledBorder.TOP: - case TitledBorder.DEFAULT_POSITION: - case TitledBorder.BELOW_TOP: - return Component.BaselineResizeBehavior.CONSTANT_ASCENT; - case TitledBorder.ABOVE_BOTTOM: - case TitledBorder.BOTTOM: - case TitledBorder.BELOW_BOTTOM: - return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT; + switch (getPosition()) { + case TitledBorder.ABOVE_TOP: + case TitledBorder.TOP: + case TitledBorder.BELOW_TOP: + return Component.BaselineResizeBehavior.CONSTANT_ASCENT; + case TitledBorder.ABOVE_BOTTOM: + case TitledBorder.BOTTOM: + case TitledBorder.BELOW_BOTTOM: + return JComponent.BaselineResizeBehavior.CONSTANT_DESCENT; } return Component.BaselineResizeBehavior.OTHER; } + private Border getBorderUI() { + Border border = getBorder(); + return border != null + ? border + : UIManager.getBorder("TitledBorder.border"); + } + + private int getPosition() { + int position = getTitlePosition(); + if (position != DEFAULT_POSITION) { + return position; + } + Object value = UIManager.get("TitledBorder.position"); + if (value instanceof Integer) { + int i = (Integer) value; + if ((0 < i) && (i <= 6)) { + return i; + } + } + else if (value instanceof String) { + String s = (String) value; + if (s.equalsIgnoreCase("ABOVE_TOP")) { + return ABOVE_TOP; + } + if (s.equalsIgnoreCase("TOP")) { + return TOP; + } + if (s.equalsIgnoreCase("BELOW_TOP")) { + return BELOW_TOP; + } + if (s.equalsIgnoreCase("ABOVE_BOTTOM")) { + return ABOVE_BOTTOM; + } + if (s.equalsIgnoreCase("BOTTOM")) { + return BOTTOM; + } + if (s.equalsIgnoreCase("BELOW_BOTTOM")) { + return BELOW_BOTTOM; + } + } + return TOP; + } + + private int getJustification(Component c) { + int justification = getTitleJustification(); + if ((justification == LEADING) || (justification == DEFAULT_JUSTIFICATION)) { + return c.getComponentOrientation().isLeftToRight() ? LEFT : RIGHT; + } + if (justification == TRAILING) { + return c.getComponentOrientation().isLeftToRight() ? RIGHT : LEFT; + } + return justification; + } + protected Font getFont(Component c) { - Font font; - if ((font = getTitleFont()) != null) { + Font font = getTitleFont(); + if (font != null) { + return font; + } + font = UIManager.getFont("TitledBorder.font"); + if (font != null) { return font; - } else if (c != null && (font = c.getFont()) != null) { - return font; + } + if (c != null) { + font = c.getFont(); + if (font != null) { + return font; + } } return new Font(Font.DIALOG, Font.PLAIN, 12); } - private static boolean computeIntersection(Rectangle dest, - int rx, int ry, int rw, int rh) { - int x1 = Math.max(rx, dest.x); - int x2 = Math.min(rx + rw, dest.x + dest.width); - int y1 = Math.max(ry, dest.y); - int y2 = Math.min(ry + rh, dest.y + dest.height); - dest.x = x1; - dest.y = y1; - dest.width = x2 - x1; - dest.height = y2 - y1; + private Color getColor(Component c) { + Color color = getTitleColor(); + if (color != null) { + return color; + } + color = UIManager.getColor("TitledBorder.titleColor"); + if (color != null) { + return color; + } + return (c != null) + ? c.getForeground() + : null; + } - if (dest.width <= 0 || dest.height <= 0) { - return false; - } - return true; + private JLabel getLabel(Component c) { + this.label.setText(getTitle()); + this.label.setFont(getFont(c)); + this.label.setForeground(getColor(c)); + this.label.setComponentOrientation(c.getComponentOrientation()); + this.label.setEnabled(c.isEnabled()); + return this.label; } }
--- a/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/plaf/basic/BasicButtonListener.java Tue Jul 20 22:21:31 2010 -0700 @@ -195,9 +195,8 @@ } ButtonModel model = b.getModel(); + model.setPressed(false); model.setArmed(false); - model.setPressed(false); - b.repaint(); }
--- a/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/plaf/basic/BasicTableHeaderUI.java Tue Jul 20 22:21:31 2010 -0700 @@ -876,7 +876,7 @@ String name = getName(); if (TOGGLE_SORT_ORDER == name) { JTable table = th.getTable(); - RowSorter sorter = table.getRowSorter(); + RowSorter sorter = table == null ? null : table.getRowSorter(); if (sorter != null) { int columnIndex = ui.getSelectedColumnIndex(); columnIndex = table.convertColumnIndexToModel(
--- a/src/share/classes/javax/swing/plaf/nimbus/skin.laf Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/javax/swing/plaf/nimbus/skin.laf Tue Jul 20 22:21:31 2010 -0700 @@ -21276,6 +21276,7 @@ <uiProperty name="centerOneTouchButtons" type="BOOLEAN" value="true"/> <uiProperty name="oneTouchButtonOffset" type="INT" value="30"/> <uiProperty name="oneTouchExpandable" type="BOOLEAN" value="false"/> + <uiProperty name="continuousLayout" type="BOOLEAN" value="true"/> </uiproperties> </style> <backgroundStates>
--- a/src/share/classes/sun/awt/PlatformFont.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/awt/PlatformFont.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,10 +25,10 @@ package sun.awt; -import java.awt.GraphicsEnvironment; import java.awt.peer.FontPeer; import java.util.Locale; import java.util.Vector; +import sun.font.SunFontManager; import sun.java2d.FontSupport; import java.nio.CharBuffer; import java.nio.ByteBuffer; @@ -57,9 +57,9 @@ protected static String osVersion; public PlatformFont(String name, int style){ - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - if (ge instanceof FontSupport) { - fontConfig = ((FontSupport)ge).getFontConfiguration(); + SunFontManager sfm = SunFontManager.getInstance(); + if (sfm instanceof FontSupport) { + fontConfig = ((FontSupport)sfm).getFontConfiguration(); } if (fontConfig == null) { return;
--- a/src/share/classes/sun/awt/SunToolkit.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/awt/SunToolkit.java Tue Jul 20 22:21:31 2010 -0700 @@ -39,6 +39,7 @@ import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import sun.util.logging.PlatformLogger; import sun.misc.SoftCache; @@ -592,7 +593,7 @@ } PostEventQueue postEventQueue = (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); - if(postEventQueue != null) { + if (postEventQueue != null) { postEventQueue.postEvent(event); } } @@ -610,16 +611,29 @@ postEvent(targetToAppContext(e.getSource()), pe); } + private static final Lock flushLock = new ReentrantLock(); + private static boolean isFlushingPendingEvents = false; + /* * Flush any pending events which haven't been posted to the AWT * EventQueue yet. */ public static void flushPendingEvents() { - AppContext appContext = AppContext.getAppContext(); - PostEventQueue postEventQueue = - (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); - if(postEventQueue != null) { - postEventQueue.flush(); + flushLock.lock(); + try { + // Don't call flushPendingEvents() recursively + if (!isFlushingPendingEvents) { + isFlushingPendingEvents = true; + AppContext appContext = AppContext.getAppContext(); + PostEventQueue postEventQueue = + (PostEventQueue)appContext.get(POST_EVENT_QUEUE_KEY); + if (postEventQueue != null) { + postEventQueue.flush(); + } + } + } finally { + isFlushingPendingEvents = false; + flushLock.unlock(); } } @@ -1930,6 +1944,25 @@ return (Window)comp; } + /** + * Returns the value of the system property indicated by the specified key. + */ + public static String getSystemProperty(final String key) { + return (String)AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + return System.getProperty(key); + } + }); + } + + /** + * Returns the boolean value of the system property indicated by the specified key. + */ + protected static Boolean getBooleanSystemProperty(String key) { + return Boolean.valueOf(AccessController. + doPrivileged(new GetBooleanAction(key))); + } + private static Boolean sunAwtDisableMixing = null; /** @@ -1938,9 +1971,7 @@ */ public synchronized static boolean getSunAwtDisableMixing() { if (sunAwtDisableMixing == null) { - sunAwtDisableMixing = Boolean.valueOf( - AccessController.doPrivileged( - new GetBooleanAction("sun.awt.disableMixing"))); + sunAwtDisableMixing = getBooleanSystemProperty("sun.awt.disableMixing"); } return sunAwtDisableMixing.booleanValue(); } @@ -2079,12 +2110,14 @@ eventQueue = eq; } - public boolean noEvents() { + public synchronized boolean noEvents() { return queueHead == null; } /* - * Continually post pending AWTEvents to the Java EventQueue. + * Continually post pending AWTEvents to the Java EventQueue. The method + * is synchronized to ensure the flush is completed before a new event + * can be posted to this queue. */ public synchronized void flush() { EventQueueItem tempQueue = queueHead;
--- a/src/share/classes/sun/font/FontUtilities.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/font/FontUtilities.java Tue Jul 20 22:21:31 2010 -0700 @@ -60,6 +60,10 @@ static final String LUCIDA_FILE_NAME = "LucidaSansRegular.ttf"; + private static boolean debugFonts = false; + private static PlatformLogger logger = null; + private static boolean logging; + // This static initializer block figures out the OS constants. static { @@ -115,6 +119,25 @@ File lucidaFile = new File(jreFontDirName + File.separator + LUCIDA_FILE_NAME); isOpenJDK = !lucidaFile.exists(); + + String debugLevel = + System.getProperty("sun.java2d.debugfonts"); + + if (debugLevel != null && !debugLevel.equals("false")) { + debugFonts = true; + logger = PlatformLogger.getLogger("sun.java2d"); + if (debugLevel.equals("warning")) { + logger.setLevel(PlatformLogger.WARNING); + } else if (debugLevel.equals("severe")) { + logger.setLevel(PlatformLogger.SEVERE); + } + } + + if (debugFonts) { + logger = PlatformLogger.getLogger("sun.java2d"); + logging = logger.isEnabled(); + } + return null; } }); @@ -140,32 +163,6 @@ */ public static final int MAX_LAYOUT_CHARCODE = 0x206F; - private static boolean debugFonts = false; - private static PlatformLogger logger = null; - private static boolean logging; - - static { - - String debugLevel = - System.getProperty("sun.java2d.debugfonts"); - - if (debugLevel != null && !debugLevel.equals("false")) { - debugFonts = true; - logger = PlatformLogger.getLogger("sun.java2d"); - if (debugLevel.equals("warning")) { - logger.setLevel(PlatformLogger.WARNING); - } else if (debugLevel.equals("severe")) { - logger.setLevel(PlatformLogger.SEVERE); - } - } - - if (debugFonts) { - logger = PlatformLogger.getLogger("sun.java2d"); - logging = logger.isEnabled(); - } - - } - /** * Calls the private getFont2D() method in java.awt.Font objects. *
--- a/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,7 +24,6 @@ */ package sun.io; -import sun.nio.cs.Surrogate; import sun.nio.cs.ext.DoubleByte; import static sun.nio.cs.CharsetMapping.*;
--- a/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,7 +24,6 @@ */ package sun.io; -import sun.nio.cs.Surrogate; import sun.nio.cs.ext.DoubleByte; import static sun.nio.cs.CharsetMapping.*;
--- a/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/java2d/HeadlessGraphicsEnvironment.java Tue Jul 20 22:21:31 2010 -0700 @@ -59,17 +59,12 @@ * Headless decorator implementation of a SunGraphicsEnvironment */ -public class HeadlessGraphicsEnvironment extends GraphicsEnvironment - implements FontSupport { +public class HeadlessGraphicsEnvironment extends GraphicsEnvironment { private GraphicsEnvironment ge; - private FontSupport fontSupport; public HeadlessGraphicsEnvironment(GraphicsEnvironment ge) { this.ge = ge; - if (ge instanceof FontSupport) { - fontSupport = (FontSupport)ge; - } } public GraphicsDevice[] getScreenDevices() @@ -101,13 +96,6 @@ public String[] getAvailableFontFamilyNames(Locale l) { return ge.getAvailableFontFamilyNames(l); } - public FontConfiguration getFontConfiguration() { - if (fontSupport != null) { - return fontSupport.getFontConfiguration(); - } - return null; - } - /* Used by FontManager : internal API */ public GraphicsEnvironment getSunGraphicsEnvironment() { return ge;
--- a/src/share/classes/sun/launcher/LauncherHelper.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/launcher/LauncherHelper.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -208,7 +208,7 @@ Method method = null; try { method = clazz.getMethod("main", String[].class); - } catch (Exception e) { + } catch (NoSuchMethodException nsme) { ostream.println(getLocalizedMessage("java.launcher.cls.error4", classname)); throw new RuntimeException("Main method not found in " + classname); @@ -225,8 +225,7 @@ throw new RuntimeException("Main method is not static in class " + classname); } - Class<?> rType = method.getReturnType(); - if (!rType.isPrimitive() || !rType.getName().equals("void")) { + if (method.getReturnType() != java.lang.Void.TYPE) { ostream.println(getLocalizedMessage("java.launcher.cls.error3", classname)); throw new RuntimeException("Main method must return a value" +
--- a/src/share/classes/sun/net/httpserver/ExchangeImpl.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/net/httpserver/ExchangeImpl.java Tue Jul 20 22:21:31 2010 -0700 @@ -52,14 +52,16 @@ boolean http10 = false; /* for formatting the Date: header */ - static TimeZone tz; - static DateFormat df; - static { - String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz"; - tz = TimeZone.getTimeZone ("GMT"); - df = new SimpleDateFormat (pattern, Locale.US); - df.setTimeZone (tz); - } + private static final String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz"; + private static final TimeZone gmtTZ = TimeZone.getTimeZone("GMT"); + private static final ThreadLocal<DateFormat> dateFormat = + new ThreadLocal<DateFormat>() { + @Override protected DateFormat initialValue() { + DateFormat df = new SimpleDateFormat(pattern, Locale.US); + df.setTimeZone(gmtTZ); + return df; + } + }; private static final String HEAD = "HEAD"; @@ -206,7 +208,7 @@ PlaceholderOutputStream o = getPlaceholderResponseBody(); tmpout.write (bytes(statusLine, 0), 0, statusLine.length()); boolean noContentToSend = false; // assume there is content - rspHdrs.set ("Date", df.format (new Date())); + rspHdrs.set ("Date", dateFormat.get().format (new Date())); /* check for response type that is not allowed to send a body */
--- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Tue Jul 20 22:21:31 2010 -0700 @@ -2331,7 +2331,7 @@ * closed the connection to the web server. */ private void disconnectWeb() throws IOException { - if (usingProxy()) { + if (usingProxy() && http.isKeepingAlive()) { responseCode = -1; // clean up, particularly, skip the content part // of a 401 error response
--- a/src/share/classes/sun/nio/cs/Surrogate.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/Surrogate.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,9 @@ * Utility class for dealing with surrogates. * * @author Mark Reinhold + * @author Martin Buchholz + * @author Ulf Zibis */ - public class Surrogate { private Surrogate() { } @@ -75,16 +76,9 @@ } /** - * Tells whether or not the given UCS-4 character is in the Basic - * Multilingual Plane, and can be represented using a single char. - */ - public static boolean isBMPCodePoint(int uc) { - return uc >> 16 == 0; - } - - /** * Tells whether or not the given UCS-4 character must be represented as a * surrogate pair in UTF-16. + * Use of {@link Character#isSupplementaryCodePoint} is generally preferred. */ public static boolean neededFor(int uc) { return Character.isSupplementaryCodePoint(uc); @@ -92,24 +86,25 @@ /** * Returns the high UTF-16 surrogate for the given supplementary UCS-4 character. + * Use of {@link Character#highSurrogate} is generally preferred. */ public static char high(int uc) { assert Character.isSupplementaryCodePoint(uc); - return (char)((uc >> 10) - + (Character.MIN_HIGH_SURROGATE - - (Character.MIN_SUPPLEMENTARY_CODE_POINT >> 10))); + return Character.highSurrogate(uc); } /** * Returns the low UTF-16 surrogate for the given supplementary UCS-4 character. + * Use of {@link Character#lowSurrogate} is generally preferred. */ public static char low(int uc) { assert Character.isSupplementaryCodePoint(uc); - return (char)((uc & 0x3ff) + Character.MIN_LOW_SURROGATE); + return Character.lowSurrogate(uc); } /** * Converts the given surrogate pair into a 32-bit UCS-4 character. + * Use of {@link Character#toCodePoint} is generally preferred. */ public static int toUCS4(char c, char d) { assert Character.isHighSurrogate(c) && Character.isLowSurrogate(d); @@ -290,8 +285,9 @@ * error() will return a descriptive result object */ public int generate(int uc, int len, CharBuffer dst) { - if (Surrogate.isBMPCodePoint(uc)) { - if (Surrogate.is(uc)) { + if (Character.isBmpCodePoint(uc)) { + char c = (char) uc; + if (Character.isSurrogate(c)) { error = CoderResult.malformedForLength(len); return -1; } @@ -299,16 +295,16 @@ error = CoderResult.OVERFLOW; return -1; } - dst.put((char)uc); + dst.put(c); error = null; return 1; - } else if (Character.isSupplementaryCodePoint(uc)) { + } else if (Character.isValidCodePoint(uc)) { if (dst.remaining() < 2) { error = CoderResult.OVERFLOW; return -1; } - dst.put(Surrogate.high(uc)); - dst.put(Surrogate.low(uc)); + dst.put(Character.highSurrogate(uc)); + dst.put(Character.lowSurrogate(uc)); error = null; return 2; } else { @@ -334,8 +330,9 @@ * error() will return a descriptive result object */ public int generate(int uc, int len, char[] da, int dp, int dl) { - if (Surrogate.isBMPCodePoint(uc)) { - if (Surrogate.is(uc)) { + if (Character.isBmpCodePoint(uc)) { + char c = (char) uc; + if (Character.isSurrogate(c)) { error = CoderResult.malformedForLength(len); return -1; } @@ -343,16 +340,16 @@ error = CoderResult.OVERFLOW; return -1; } - da[dp] = (char)uc; + da[dp] = c; error = null; return 1; - } else if (Character.isSupplementaryCodePoint(uc)) { + } else if (Character.isValidCodePoint(uc)) { if (dl - dp < 2) { error = CoderResult.OVERFLOW; return -1; } - da[dp] = Surrogate.high(uc); - da[dp + 1] = Surrogate.low(uc); + da[dp] = Character.highSurrogate(uc); + da[dp + 1] = Character.lowSurrogate(uc); error = null; return 2; } else {
--- a/src/share/classes/sun/nio/cs/UTF_32Coder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/UTF_32Coder.java Tue Jul 20 22:21:31 2010 -0700 @@ -86,22 +86,21 @@ src.position(mark); } } - while (src.remaining() > 3) { + while (src.remaining() >= 4) { cp = getCP(src); - if (cp < 0 || cp > Surrogate.UCS4_MAX) { - return CoderResult.malformedForLength(4); - } - if (cp < Surrogate.UCS4_MIN) { + if (Character.isBmpCodePoint(cp)) { if (!dst.hasRemaining()) return CoderResult.OVERFLOW; mark += 4; - dst.put((char)cp); - } else { + dst.put((char) cp); + } else if (Character.isValidCodePoint(cp)) { if (dst.remaining() < 2) return CoderResult.OVERFLOW; mark += 4; - dst.put(Surrogate.high(cp)); - dst.put(Surrogate.low(cp)); + dst.put(Character.highSurrogate(cp)); + dst.put(Character.lowSurrogate(cp)); + } else { + return CoderResult.malformedForLength(4); } } return CoderResult.UNDERFLOW; @@ -154,7 +153,12 @@ try { while (src.hasRemaining()) { char c = src.get(); - if (Character.isHighSurrogate(c)) { + if (!Character.isSurrogate(c)) { + if (dst.remaining() < 4) + return CoderResult.OVERFLOW; + mark++; + put(c, dst); + } else if (Character.isHighSurrogate(c)) { if (!src.hasRemaining()) return CoderResult.UNDERFLOW; char low = src.get(); @@ -162,17 +166,13 @@ if (dst.remaining() < 4) return CoderResult.OVERFLOW; mark += 2; - put(Surrogate.toUCS4(c, low), dst); + put(Character.toCodePoint(c, low), dst); } else { return CoderResult.malformedForLength(1); } - } else if (Character.isLowSurrogate(c)) { + } else { + // assert Character.isLowSurrogate(c); return CoderResult.malformedForLength(1); - } else { - if (dst.remaining() < 4) - return CoderResult.OVERFLOW; - mark++; - put(c, dst); } } return CoderResult.UNDERFLOW;
--- a/src/share/classes/sun/nio/cs/UTF_8.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/UTF_8.java Tue Jul 20 22:21:31 2010 -0700 @@ -102,7 +102,7 @@ // [F1..F3] [80..BF] [80..BF] [80..BF] // [F4] [80..8F] [80..BF] [80..BF] // only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...] - // will be checked by Surrogate.neededFor(uc) + // will be checked by Character.isSupplementaryCodePoint(uc) private static boolean isMalformed4(int b2, int b3, int b4) { return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 || (b4 & 0xc0) != 0x80; @@ -207,15 +207,15 @@ // ASCII only loop while (dp < dlASCII && sa[sp] >= 0) - da[dp++] = (char)sa[sp++]; + da[dp++] = (char) sa[sp++]; while (sp < sl) { int b1 = sa[sp]; - if (b1 >= 0) { + if (b1 >= 0) { // 1 byte, 7 bits: 0xxxxxxx if (dp >= dl) return xflow(src, sp, sl, dst, dp, 1); - da[dp++] = (char)b1; + da[dp++] = (char) b1; sp++; } else if ((b1 >> 5) == -2) { // 2 bytes, 11 bits: 110xxxxx 10xxxxxx @@ -224,7 +224,10 @@ int b2 = sa[sp + 1]; if (isMalformed2(b1, b2)) return malformed(src, sp, dst, dp, 2); - da[dp++] = (char) (((b1 << 6) ^ b2) ^ 0x0f80); + da[dp++] = (char) (((b1 << 6) ^ b2) + ^ + (((byte) 0xC0 << 6) ^ + ((byte) 0x80 << 0))); sp += 2; } else if ((b1 >> 4) == -2) { // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx @@ -234,7 +237,13 @@ int b3 = sa[sp + 2]; if (isMalformed3(b1, b2, b3)) return malformed(src, sp, dst, dp, 3); - da[dp++] = (char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80); + da[dp++] = (char) + ((b1 << 12) ^ + (b2 << 6) ^ + (b3 ^ + (((byte) 0xE0 << 12) ^ + ((byte) 0x80 << 6) ^ + ((byte) 0x80 << 0)))); sp += 3; } else if ((b1 >> 3) == -2) { // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx @@ -243,16 +252,21 @@ int b2 = sa[sp + 1]; int b3 = sa[sp + 2]; int b4 = sa[sp + 3]; - int uc = ((b1 & 0x07) << 18) | - ((b2 & 0x3f) << 12) | - ((b3 & 0x3f) << 06) | - (b4 & 0x3f); + 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) || - !Surrogate.neededFor(uc)) { + // shortest form check + !Character.isSupplementaryCodePoint(uc)) { return malformed(src, sp, dst, dp, 4); } - da[dp++] = Surrogate.high(uc); - da[dp++] = Surrogate.low(uc); + da[dp++] = Character.highSurrogate(uc); + da[dp++] = Character.lowSurrogate(uc); sp += 4; } else return malformed(src, sp, dst, dp, 1); @@ -270,8 +284,8 @@ if (b1 >= 0) { // 1 byte, 7 bits: 0xxxxxxx if (dst.remaining() < 1) - return xflow(src, mark, 1); //overflow - dst.put((char)b1); + return xflow(src, mark, 1); // overflow + dst.put((char) b1); mark++; } else if ((b1 >> 5) == -2) { // 2 bytes, 11 bits: 110xxxxx 10xxxxxx @@ -280,7 +294,10 @@ int b2 = src.get(); if (isMalformed2(b1, b2)) return malformed(src, mark, 2); - dst.put((char) (((b1 << 6) ^ b2) ^ 0x0f80)); + dst.put((char) (((b1 << 6) ^ b2) + ^ + (((byte) 0xC0 << 6) ^ + ((byte) 0x80 << 0)))); mark += 2; } else if ((b1 >> 4) == -2) { // 3 bytes, 16 bits: 1110xxxx 10xxxxxx 10xxxxxx @@ -290,7 +307,13 @@ int b3 = src.get(); if (isMalformed3(b1, b2, b3)) return malformed(src, mark, 3); - dst.put((char) (((b1 << 12) ^ (b2 << 6) ^ b3) ^ 0x1f80)); + dst.put((char) + ((b1 << 12) ^ + (b2 << 6) ^ + (b3 ^ + (((byte) 0xE0 << 12) ^ + ((byte) 0x80 << 6) ^ + ((byte) 0x80 << 0))))); mark += 3; } else if ((b1 >> 3) == -2) { // 4 bytes, 21 bits: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx @@ -299,16 +322,21 @@ int b2 = src.get(); int b3 = src.get(); int b4 = src.get(); - int uc = ((b1 & 0x07) << 18) | - ((b2 & 0x3f) << 12) | - ((b3 & 0x3f) << 06) | - (b4 & 0x3f); + 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) || - !Surrogate.neededFor(uc)) { // shortest form check + // shortest form check + !Character.isSupplementaryCodePoint(uc)) { return malformed(src, mark, 4); } - dst.put(Surrogate.high(uc)); - dst.put(Surrogate.low(uc)); + dst.put(Character.highSurrogate(uc)); + dst.put(Character.lowSurrogate(uc)); mark += 4; } else { return malformed(src, mark, 1); @@ -366,7 +394,7 @@ int dl = dst.arrayOffset() + dst.limit(); int dlASCII = dp + Math.min(sl - sp, dl - dp); - //ASCII only loop + // ASCII only loop while (dp < dlASCII && sa[sp] < '\u0080') da[dp++] = (byte) sa[sp++]; while (sp < sl) { @@ -380,7 +408,7 @@ // 2 bytes, 11 bits if (dl - dp < 2) return overflow(src, sp, dst, dp); - da[dp++] = (byte)(0xc0 | ((c >> 06))); + da[dp++] = (byte)(0xc0 | (c >> 6)); da[dp++] = (byte)(0x80 | (c & 0x3f)); } else if (Character.isSurrogate(c)) { // Have a surrogate pair @@ -395,7 +423,7 @@ return overflow(src, sp, dst, dp); da[dp++] = (byte)(0xf0 | ((uc >> 18))); da[dp++] = (byte)(0x80 | ((uc >> 12) & 0x3f)); - da[dp++] = (byte)(0x80 | ((uc >> 06) & 0x3f)); + da[dp++] = (byte)(0x80 | ((uc >> 6) & 0x3f)); da[dp++] = (byte)(0x80 | (uc & 0x3f)); sp++; // 2 chars } else { @@ -403,7 +431,7 @@ if (dl - dp < 3) return overflow(src, sp, dst, dp); da[dp++] = (byte)(0xe0 | ((c >> 12))); - da[dp++] = (byte)(0x80 | ((c >> 06) & 0x3f)); + da[dp++] = (byte)(0x80 | ((c >> 6) & 0x3f)); da[dp++] = (byte)(0x80 | (c & 0x3f)); } sp++; @@ -427,7 +455,7 @@ // 2 bytes, 11 bits if (dst.remaining() < 2) return overflow(src, mark); - dst.put((byte)(0xc0 | ((c >> 06)))); + dst.put((byte)(0xc0 | (c >> 6))); dst.put((byte)(0x80 | (c & 0x3f))); } else if (Character.isSurrogate(c)) { // Have a surrogate pair @@ -442,15 +470,15 @@ return overflow(src, mark); dst.put((byte)(0xf0 | ((uc >> 18)))); dst.put((byte)(0x80 | ((uc >> 12) & 0x3f))); - dst.put((byte)(0x80 | ((uc >> 06) & 0x3f))); + dst.put((byte)(0x80 | ((uc >> 6) & 0x3f))); dst.put((byte)(0x80 | (uc & 0x3f))); - mark++; //2 chars + mark++; // 2 chars } else { // 3 bytes, 16 bits if (dst.remaining() < 3) return overflow(src, mark); dst.put((byte)(0xe0 | ((c >> 12)))); - dst.put((byte)(0x80 | ((c >> 06) & 0x3f))); + dst.put((byte)(0x80 | ((c >> 6) & 0x3f))); dst.put((byte)(0x80 | (c & 0x3f))); } mark++;
--- a/src/share/classes/sun/nio/cs/UnicodeEncoder.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/UnicodeEncoder.java Tue Jul 20 22:21:31 2010 -0700 @@ -93,8 +93,8 @@ if (dst.remaining() < 4) return CoderResult.OVERFLOW; mark += 2; - put(Surrogate.high(d), dst); - put(Surrogate.low(d), dst); + put(Character.highSurrogate(d), dst); + put(Character.lowSurrogate(d), dst); } return CoderResult.UNDERFLOW; } finally {
--- a/src/share/classes/sun/nio/cs/ext/EUC_TW.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/ext/EUC_TW.java Tue Jul 20 22:21:31 2010 -0700 @@ -34,7 +34,6 @@ import java.nio.charset.CoderResult; import java.util.Arrays; import sun.nio.cs.HistoricallyNamedCharset; -import sun.nio.cs.Surrogate; import static sun.nio.cs.CharsetMapping.*; public class EUC_TW extends Charset implements HistoricallyNamedCharset @@ -159,8 +158,8 @@ c1[0] = c; return c1; } else { - c2[0] = Surrogate.high(0x20000 + c); - c2[1] = Surrogate.low(0x20000 + c); + c2[0] = Character.highSurrogate(0x20000 + c); + c2[1] = Character.lowSurrogate(0x20000 + c); return c2; } } @@ -441,7 +440,7 @@ } static int encode(char hi, char low, byte[] bb) { - int c = Surrogate.toUCS4(hi, low); + int c = Character.toCodePoint(hi, low); if ((c & 0xf0000) != 0x20000) return -1; c -= 0x20000;
--- a/src/share/classes/sun/nio/cs/ext/GB18030.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/ext/GB18030.java Tue Jul 20 22:21:31 2010 -0700 @@ -12628,7 +12628,7 @@ if (Character.isSurrogate(c)) { if ((condensedKey=sgp.parse(c, sa, sp, sl)) < 0) return sgp.error(); - // Surogate.toUCS4 looks like + // Character.toCodePoint looks like // (((high & 0x3ff) << 10) | (low & 0x3ff)) + 0x10000; // so we add (0x2e248 - 0x10000) to get the "key". condensedKey += 0x1E248;
--- a/src/share/classes/sun/nio/cs/ext/IBM33722.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/ext/IBM33722.java Tue Jul 20 22:21:31 2010 -0700 @@ -36,7 +36,6 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import sun.nio.cs.HistoricallyNamedCharset; -import sun.nio.cs.Surrogate; public class IBM33722 extends Charset
--- a/src/share/classes/sun/nio/cs/ext/IBM964.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/nio/cs/ext/IBM964.java Tue Jul 20 22:21:31 2010 -0700 @@ -36,7 +36,6 @@ import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import sun.nio.cs.HistoricallyNamedCharset; -import sun.nio.cs.Surrogate; public class IBM964 extends Charset
--- a/src/share/classes/sun/security/krb5/Credentials.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/Credentials.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,7 @@ import sun.security.krb5.internal.*; import sun.security.krb5.internal.ccache.CredentialsCache; -import sun.security.krb5.internal.ktab.*; import sun.security.krb5.internal.crypto.EType; -import java.io.File; import java.io.IOException; import java.util.Date; import java.net.InetAddress; @@ -506,59 +504,6 @@ return result; } - - /** - * Gets service credential from key table. The credential is used to - * decrypt the received client message - * and authenticate the client by verifying the client's credential. - * - * @param serviceName the name of service, using format component@realm - * @param keyTabFile the file of key table. - * @return a <code>KrbCreds</code> object. - */ - public static Credentials getServiceCreds(String serviceName, - File keyTabFile) { - EncryptionKey k = null; - PrincipalName service = null; - Credentials result = null; - try { - service = new PrincipalName(serviceName); - if (service.getRealm() == null) { - String realm = Config.getInstance().getDefaultRealm(); - if (realm == null) { - return null; - } else { - service.setRealm(realm); - } - } - } catch (RealmException e) { - if (DEBUG) { - e.printStackTrace(); - } - return null; - } catch (KrbException e) { - if (DEBUG) { - e.printStackTrace(); - } - return null; - } - KeyTab kt; - if (keyTabFile == null) { - kt = KeyTab.getInstance(); - } else { - kt = KeyTab.getInstance(keyTabFile); - } - if ((kt != null) && (kt.findServiceEntry(service))) { - k = kt.readServiceKey(service); - result = new Credentials(null, service, null, null, null, - null, null, null, null, null); - result.serviceKey = k; - } - return result; - } - - - /** * Acquires credentials for a specified service using initial credential. * When the service has a different realm
--- a/src/share/classes/sun/security/krb5/EncryptedData.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/EncryptedData.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -336,38 +336,29 @@ } /** - * Reset data stream after decryption, remove redundant bytes. + * Reset asn.1 data stream after decryption, remove redundant bytes. * @param data the decrypted data from decrypt(). - * @param encoded true if the encrypted data is ASN1 encoded data, - * false if the encrypted data is not ASN1 encoded data. * @return the reset byte array which holds exactly one asn1 datum * including its tag and length. * */ - public byte[] reset(byte[] data, boolean encoded) { + public byte[] reset(byte[] data) { byte[] bytes = null; - // if it is encoded data, we use length field to + // for asn.1 encoded data, we use length field to // determine the data length and remove redundant paddings. - if (encoded) { - if ((data[1] & 0xFF) < 128) { - bytes = new byte[data[1] + 2]; - System.arraycopy(data, 0, bytes, 0, data[1] + 2); - } else - if ((data[1] & 0xFF) > 128) { - int len = data[1] & (byte)0x7F; - int result = 0; - for (int i = 0; i < len; i++) { - result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1)); - } - bytes = new byte[result + len + 2]; - System.arraycopy(data, 0, bytes, 0, result + len + 2); + if ((data[1] & 0xFF) < 128) { + bytes = new byte[data[1] + 2]; + System.arraycopy(data, 0, bytes, 0, data[1] + 2); + } else { + if ((data[1] & 0xFF) > 128) { + int len = data[1] & (byte)0x7F; + int result = 0; + for (int i = 0; i < len; i++) { + result |= (data[i + 2] & 0xFF) << (8 * (len - i - 1)); } - } else { - // if it is not encoded, which happens in GSS tokens, - // we remove padding data according to padding pattern. - bytes = new byte[data.length - data[data.length - 1]]; - System.arraycopy(data, 0, bytes, 0, - data.length - data[data.length - 1]); + bytes = new byte[result + len + 2]; + System.arraycopy(data, 0, bytes, 0, result + len + 2); + } } return bytes; }
--- a/src/share/classes/sun/security/krb5/KrbApRep.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbApRep.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,7 +130,7 @@ byte[] temp = rep.encPart.decrypt(tgs_creds.key, KeyUsage.KU_ENC_AP_REP_PART); - byte[] enc_ap_rep_part = rep.encPart.reset(temp, true); + byte[] enc_ap_rep_part = rep.encPart.reset(temp); encoding = new DerValue(enc_ap_rep_part); encPart = new EncAPRepPart(encoding);
--- a/src/share/classes/sun/security/krb5/KrbApReq.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbApReq.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -279,14 +279,14 @@ byte[] bytes = apReqMessg.ticket.encPart.decrypt(dkey, KeyUsage.KU_TICKET); - byte[] temp = apReqMessg.ticket.encPart.reset(bytes, true); + byte[] temp = apReqMessg.ticket.encPart.reset(bytes); EncTicketPart enc_ticketPart = new EncTicketPart(temp); checkPermittedEType(enc_ticketPart.key.getEType()); byte[] bytes2 = apReqMessg.authenticator.decrypt(enc_ticketPart.key, KeyUsage.KU_AP_REQ_AUTHENTICATOR); - byte[] temp2 = apReqMessg.authenticator.reset(bytes2, true); + byte[] temp2 = apReqMessg.authenticator.reset(bytes2); authenticator = new Authenticator(temp2); ctime = authenticator.ctime; cusec = authenticator.cusec;
--- a/src/share/classes/sun/security/krb5/KrbAsRep.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbAsRep.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,7 +95,7 @@ byte[] enc_as_rep_bytes = rep.encPart.decrypt(dkey, KeyUsage.KU_ENC_AS_REP_PART); - byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes, true); + byte[] enc_as_rep_part = rep.encPart.reset(enc_as_rep_bytes); encoding = new DerValue(enc_as_rep_part); EncASRepPart enc_part = new EncASRepPart(encoding);
--- a/src/share/classes/sun/security/krb5/KrbCred.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbCred.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,7 +130,7 @@ byte[] temp = credMessg.encPart.decrypt(key, KeyUsage.KU_ENC_KRB_CRED_PART); - byte[] plainText = credMessg.encPart.reset(temp, true); + byte[] plainText = credMessg.encPart.reset(temp); DerValue encoding = new DerValue(plainText); EncKrbCredPart encPart = new EncKrbCredPart(encoding);
--- a/src/share/classes/sun/security/krb5/KrbPriv.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbPriv.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ package sun.security.krb5; -import sun.security.krb5.EncryptionKey; import sun.security.krb5.internal.*; import sun.security.krb5.internal.crypto.*; import sun.security.util.*; @@ -159,7 +158,7 @@ byte[] bytes = krb_priv.encPart.decrypt(key, KeyUsage.KU_ENC_KRB_PRIV_PART); - byte[] temp = krb_priv.encPart.reset(bytes, true); + byte[] temp = krb_priv.encPart.reset(bytes); DerValue ref = new DerValue(temp); EncKrbPrivPart enc_part = new EncKrbPrivPart(ref);
--- a/src/share/classes/sun/security/krb5/KrbTgsRep.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/KrbTgsRep.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -79,7 +79,7 @@ tgsReq.usedSubkey() ? KeyUsage.KU_ENC_TGS_REP_PART_SUBKEY : KeyUsage.KU_ENC_TGS_REP_PART_SESSKEY); - byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes, true); + byte[] enc_tgs_rep_part = rep.encPart.reset(enc_tgs_rep_bytes); ref = new DerValue(enc_tgs_rep_part); EncTGSRepPart enc_part = new EncTGSRepPart(ref); rep.ticket.sname.setRealm(rep.ticket.realm);
--- a/src/share/classes/sun/security/krb5/internal/crypto/EType.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/internal/crypto/EType.java Tue Jul 20 22:21:31 2010 -0700 @@ -185,20 +185,20 @@ // is set to false. private static final int[] BUILTIN_ETYPES = new int[] { - EncryptedData.ETYPE_DES_CBC_MD5, - EncryptedData.ETYPE_DES_CBC_CRC, + EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96, + EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96, + EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD, EncryptedData.ETYPE_ARCFOUR_HMAC, - EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD, - EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96, - EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96, + EncryptedData.ETYPE_DES_CBC_CRC, + EncryptedData.ETYPE_DES_CBC_MD5, }; private static final int[] BUILTIN_ETYPES_NOAES256 = new int[] { - EncryptedData.ETYPE_DES_CBC_MD5, - EncryptedData.ETYPE_DES_CBC_CRC, + EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96, + EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD, EncryptedData.ETYPE_ARCFOUR_HMAC, - EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD, - EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96, + EncryptedData.ETYPE_DES_CBC_CRC, + EncryptedData.ETYPE_DES_CBC_MD5, }; @@ -217,8 +217,8 @@ result = BUILTIN_ETYPES; } if (!ALLOW_WEAK_CRYPTO) { - // The first 2 etypes are now weak ones - return Arrays.copyOfRange(result, 2, result.length); + // The last 2 etypes are now weak ones + return Arrays.copyOfRange(result, 0, result.length - 2); } return result; }
--- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -228,37 +228,6 @@ } /** - * Reads the service key from the keytab file. - * @param service the PrincipalName of the requested service. - * @return the last service key in the keytab with the highest kvno - */ - public EncryptionKey readServiceKey(PrincipalName service) { - KeyTabEntry entry = null; - EncryptionKey key = null; - if (entries != null) { - // Find latest entry for this service that has an etype - // that has been configured for use - for (int i = entries.size()-1; i >= 0; i--) { - entry = entries.elementAt(i); - if (entry.service.match(service)) { - if (EType.isSupported(entry.keyType)) { - if (key == null || - entry.keyVersion > key.getKeyVersionNumber()) { - key = new EncryptionKey(entry.keyblock, - entry.keyType, - new Integer(entry.keyVersion)); - } - } else if (DEBUG) { - System.out.println("Found unsupported keytype (" + - entry.keyType + ") for " + service); - } - } - } - } - return key; - } - - /** * Reads all keys for a service from the keytab file that have * etypes that have been configured for use. If there are multiple * keys with same etype, the one with the highest kvno is returned. @@ -309,7 +278,7 @@ Arrays.sort(retVal, new Comparator<EncryptionKey>() { @Override public int compare(EncryptionKey o1, EncryptionKey o2) { - if (etypes != null && etypes != EType.getBuiltInDefaults()) { + if (etypes != null) { int o1EType = o1.getEType(); int o2EType = o2.getEType(); if (o1EType != o2EType) { @@ -320,6 +289,9 @@ return 1; } } + // Neither o1EType nor o2EType in default_tkt_enctypes, + // therefore won't be used in AS-REQ. We do not care + // about their order, use kvno is OK. } } return o2.getKeyVersionNumber().intValue()
--- a/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,24 +180,15 @@ String alias; }; - private static class KeyId { - byte[] keyId; - - KeyId(byte[] keyId) { + // A certificate with its PKCS #9 attributes + private static class CertEntry { + final X509Certificate cert; + final byte[] keyId; + final String alias; + CertEntry(X509Certificate cert, byte[] keyId, String alias) { + this.cert = cert; this.keyId = keyId; - } - public int hashCode() { - int hash = 0; - - for (int i = 0; i < keyId.length; i++) - hash += keyId[i]; - return hash; - } - public boolean equals(Object obj) { - if (!(obj instanceof KeyId)) - return false; - KeyId that = (KeyId)obj; - return (Arrays.equals(this.keyId, that.keyId)); + this.alias = alias; } } @@ -209,7 +200,9 @@ new Hashtable<String, KeyEntry>(); private ArrayList<KeyEntry> keyList = new ArrayList<KeyEntry>(); - private LinkedHashMap<Object, X509Certificate> certs = new LinkedHashMap<Object, X509Certificate>(); + private LinkedHashMap<X500Principal, X509Certificate> certsMap = + new LinkedHashMap<X500Principal, X509Certificate>(); + private ArrayList<CertEntry> certEntries = new ArrayList<CertEntry>(); /** * Returns the key associated with the given alias, using the given @@ -472,6 +465,15 @@ KeyEntry entry = new KeyEntry(); entry.date = new Date(); + try { + // set the keyId to current date + entry.keyId = ("Time " + (entry.date).getTime()).getBytes("UTF8"); + } catch (UnsupportedEncodingException ex) { + // Won't happen + } + // set the alias + entry.alias = alias.toLowerCase(); + entry.protectedPrivKey = key.clone(); if (chain != null) { entry.chain = chain.clone(); @@ -1027,10 +1029,9 @@ // All Certs should have a unique friendlyName. // This change is made to meet NSS requirements. byte[] bagAttrs = null; - String friendlyName = cert.getSubjectX500Principal().getName(); if (i == 0) { // Only End-Entity Cert should have a localKeyId. - bagAttrs = getBagAttributes(friendlyName, entry.keyId); + bagAttrs = getBagAttributes(entry.alias, entry.keyId); } else { // Trusted root CA certs and Intermediate CA certs do not // need to have a localKeyId, and hence localKeyId is null @@ -1038,7 +1039,8 @@ // NSS pkcs12 library requires trusted CA certs in the // certificate chain to have unique or null localKeyID. // However, IE/OpenSSL do not impose this restriction. - bagAttrs = getBagAttributes(friendlyName, null); + bagAttrs = getBagAttributes( + cert.getSubjectX500Principal().getName(), null); } if (bagAttrs != null) { safeBag.write(bagAttrs); @@ -1333,24 +1335,49 @@ if (entry.keyId != null) { ArrayList<X509Certificate> chain = new ArrayList<X509Certificate>(); - X509Certificate cert = certs.get(new KeyId(entry.keyId)); + X509Certificate cert = findMatchedCertificate(entry); while (cert != null) { chain.add(cert); X500Principal issuerDN = cert.getIssuerX500Principal(); if (issuerDN.equals(cert.getSubjectX500Principal())) { break; } - cert = certs.get(issuerDN); + cert = certsMap.get(issuerDN); } /* Update existing KeyEntry in entries table */ if (chain.size() > 0) entry.chain = chain.toArray(new Certificate[chain.size()]); } } - certs.clear(); + certEntries.clear(); + certsMap.clear(); keyList.clear(); } + /** + * Locates a matched CertEntry from certEntries, and returns its cert. + * @param entry the KeyEntry to match + * @return a certificate, null if not found + */ + private X509Certificate findMatchedCertificate(KeyEntry entry) { + CertEntry keyIdMatch = null; + CertEntry aliasMatch = null; + for (CertEntry ce: certEntries) { + if (Arrays.equals(entry.keyId, ce.keyId)) { + keyIdMatch = ce; + if (entry.alias.equalsIgnoreCase(ce.alias)) { + // Full match! + return ce.cert; + } + } else if (entry.alias.equalsIgnoreCase(ce.alias)) { + aliasMatch = ce; + } + } + // keyId match first, for compatibility + if (keyIdMatch != null) return keyIdMatch.cert; + else if (aliasMatch != null) return aliasMatch.cert; + else return null; + } private void loadSafeContents(DerInputStream stream, char[] password) throws IOException, NoSuchAlgorithmException, CertificateException @@ -1491,19 +1518,12 @@ keyId = "01".getBytes("UTF8"); } } - if (keyId != null) { - KeyId keyid = new KeyId(keyId); - if (!certs.containsKey(keyid)) - certs.put(keyid, cert); - } - if (alias != null) { - if (!certs.containsKey(alias)) - certs.put(alias, cert); - } + certEntries.add(new CertEntry(cert, keyId, alias)); X500Principal subjectDN = cert.getSubjectX500Principal(); if (subjectDN != null) { - if (!certs.containsKey(subjectDN)) - certs.put(subjectDN, cert); + if (!certsMap.containsKey(subjectDN)) { + certsMap.put(subjectDN, cert); + } } } }
--- a/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Tue Jul 20 22:21:31 2010 -0700 @@ -212,7 +212,7 @@ byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET); // Reset data stream after decryption, remove redundant bytes - byte[] temp = encPart.reset(bytes, true); + byte[] temp = encPart.reset(bytes); EncTicketPart encTicketPart = new EncTicketPart(temp); // Record the Kerberos Principals
--- a/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ import java.io.*; import java.security.*; -import java.security.interfaces.*; +import java.util.Arrays; import javax.net.ssl.*; @@ -128,8 +128,8 @@ "are not supported for TLS Kerberos cipher suites"); } - // Decrypt premaster secret - try { + // Decrypt premaster secret + try { EncryptedData data = new EncryptedData(sessionKey.getEType(), null /* optional kvno */, encrypted); @@ -141,8 +141,25 @@ } } - // Reset data stream after decryption, remove redundant bytes - preMaster = data.reset(temp, false); + // Remove padding bytes after decryption. Only DES and DES3 have + // paddings and we don't support DES3 in TLS (see above) + + if (temp.length == 52 && + data.getEType() == EncryptedData.ETYPE_DES_CBC_CRC) { + // For des-cbc-crc, 4 paddings. Value can be 0x04 or 0x00. + if (paddingByteIs(temp, 52, (byte)4) || + paddingByteIs(temp, 52, (byte)0)) { + temp = Arrays.copyOf(temp, 48); + } + } else if (temp.length == 56 && + data.getEType() == EncryptedData.ETYPE_DES_CBC_MD5) { + // For des-cbc-md5, 8 paddings with 0x08, or no padding + if (paddingByteIs(temp, 56, (byte)8)) { + temp = Arrays.copyOf(temp, 48); + } + } + + preMaster = temp; protocolVersion = ProtocolVersion.valueOf(preMaster[0], preMaster[1]); @@ -191,6 +208,19 @@ } } + /** + * Checks if all paddings of data are b + * @param data the block with padding + * @param len length of data, >= 48 + * @param b expected padding byte + */ + private static boolean paddingByteIs(byte[] data, int len, byte b) { + for (int i=48; i<len; i++) { + if (data[i] != b) return false; + } + return true; + } + /* * Used by server to generate premaster secret in case of * problem decoding ticket.
--- a/src/share/classes/sun/swing/SwingUtilities2.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/classes/sun/swing/SwingUtilities2.java Tue Jul 20 22:21:31 2010 -0700 @@ -438,8 +438,12 @@ // c may be null here. String clipString = "..."; availTextWidth -= SwingUtilities2.stringWidth(c, fm, clipString); + if (availTextWidth <= 0) { + //can not fit any characters + return clipString; + } + boolean needsTextLayout; - synchronized (charsBufferLock) { int stringLength = syncCharsBuffer(string); needsTextLayout =
--- a/src/share/native/sun/awt/image/BufImgSurfaceData.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/share/native/sun/awt/image/BufImgSurfaceData.c Tue Jul 20 22:21:31 2010 -0700 @@ -111,6 +111,10 @@ { BufImgSDOps *bisdo = (BufImgSDOps*)SurfaceData_InitOps(env, bisd, sizeof(BufImgSDOps)); + if (bisdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } bisdo->sdOps.Lock = BufImg_Lock; bisdo->sdOps.GetRasInfo = BufImg_GetRasInfo; bisdo->sdOps.Release = BufImg_Release;
--- a/src/solaris/bin/java_md.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/bin/java_md.c Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -183,13 +183,9 @@ } void -CreateExecutionEnvironment(int *_argcp, - char ***_argvp, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv) { +CreateExecutionEnvironment(int *pargc, char ***pargv, + char jrepath[], jint so_jrepath, + char jvmpath[], jint so_jvmpath) { /* * First, determine if we are running the desired data model. If we * are running the desired data model, all the error messages @@ -200,18 +196,17 @@ * os/processor combination has dual mode capabilities. */ - int original_argc = *_argcp; jboolean jvmpathExists; /* Compute/set the name of the executable */ - SetExecname(*_argvp); + SetExecname(*pargv); /* Check data model flags, and exec process, if needed */ { char *arch = (char *)GetArch(); /* like sparc or sparcv9 */ char * jvmtype = NULL; - int argc = *_argcp; - char **argv = original_argv; + int argc = *pargc; + char **argv = *pargv; int running = CURRENT_DATA_MODEL; @@ -233,7 +228,7 @@ { /* open new scope to declare local variables */ int i; - newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(*newargv)); + newargv = (char **)JLI_MemAlloc((argc+1) * sizeof(char*)); newargv[newargc++] = argv[0]; /* scan for data model arguments and remove from argument list; @@ -293,7 +288,11 @@ } jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_FALSE); + jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); + if (JLI_StrCmp(jvmtype, "ERROR") == 0) { + JLI_ReportErrorMessage(CFG_ERROR9); + exit(4); + } if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, arch )) { JLI_ReportErrorMessage(CFG_ERROR8, jvmtype, jvmpath); @@ -309,7 +308,9 @@ if (running != wanted) { /* Find out where the JRE is that we will be using. */ if (!GetJREPath(jrepath, so_jrepath, GetArchPath(wanted), JNI_TRUE)) { - goto EndDataModelSpeculate; + /* give up and let other code report error message */ + JLI_ReportErrorMessage(JRE_ERROR2, wanted); + exit(1); } /* @@ -317,16 +318,21 @@ * selection options. */ if (ReadKnownVMs(jrepath, GetArchPath(wanted), JNI_TRUE) < 1) { - goto EndDataModelSpeculate; + /* give up and let other code report error message */ + JLI_ReportErrorMessage(JRE_ERROR2, wanted); + exit(1); } jvmpath[0] = '\0'; - jvmtype = CheckJvmType(_argcp, _argvp, JNI_TRUE); + jvmtype = CheckJvmType(pargc, pargv, JNI_TRUE); + if (JLI_StrCmp(jvmtype, "ERROR") == 0) { + JLI_ReportErrorMessage(CFG_ERROR9); + exit(4); + } + /* exec child can do error checking on the existence of the path */ jvmpathExists = GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath, GetArchPath(wanted)); } - EndDataModelSpeculate: /* give up and let other code report error message */ - ; #else JLI_ReportErrorMessage(JRE_ERROR2, wanted); exit(1); @@ -398,9 +404,9 @@ struct stat s; if (JLI_StrChr(jvmtype, '/')) { - sprintf(jvmpath, "%s/" JVM_DLL, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s/" JVM_DLL, jvmtype); } else { - sprintf(jvmpath, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s/lib/%s/%s/" JVM_DLL, jrepath, arch, jvmtype); } JLI_TraceLauncher("Does `%s' exist ... ", jvmpath); @@ -424,26 +430,24 @@ if (GetApplicationHome(path, pathsize)) { /* Is JRE co-located with the application? */ - sprintf(libjava, "%s/lib/%s/" JAVA_DLL, path, arch); + JLI_Snprintf(libjava, sizeof(libjava), "%s/lib/%s/" JAVA_DLL, path, arch); if (access(libjava, F_OK) == 0) { - goto found; + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; } /* Does the app ship a private JRE in <apphome>/jre directory? */ - sprintf(libjava, "%s/jre/lib/%s/" JAVA_DLL, path, arch); + JLI_Snprintf(libjava, sizeof(libjava), "%s/jre/lib/%s/" JAVA_DLL, path, arch); if (access(libjava, F_OK) == 0) { JLI_StrCat(path, "/jre"); - goto found; + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; } } if (!speculative) JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); return JNI_FALSE; - - found: - JLI_TraceLauncher("JRE path is %s\n", path); - return JNI_TRUE; } jboolean @@ -463,14 +467,18 @@ int location; fp = fopen(jvmpath, "r"); - if(fp == NULL) - goto error; + if (fp == NULL) { + JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); + return JNI_FALSE; + } /* read in elf header */ count = fread((void*)(&elf_head), sizeof(Elf32_Ehdr), 1, fp); fclose(fp); - if(count < 1) - goto error; + if (count < 1) { + JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); + return JNI_FALSE; + } /* * Check for running a server vm (compiled with -xarch=v8plus) @@ -481,41 +489,42 @@ * does not have to be checked for in binaries with an LP64 data * model. */ - if(elf_head.e_machine == EM_SPARC32PLUS) { + if (elf_head.e_machine == EM_SPARC32PLUS) { char buf[257]; /* recommended buffer size from sysinfo man page */ long length; char* location; length = sysinfo(SI_ISALIST, buf, 257); - if(length > 0) { - location = JLI_StrStr(buf, "sparcv8plus "); - if(location == NULL) { + if (length > 0) { + location = JLI_StrStr(buf, "sparcv8plus "); + if (location == NULL) { JLI_ReportErrorMessage(JVM_ERROR3); return JNI_FALSE; } } } #endif - JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); - goto error; + JLI_ReportErrorMessage(DLL_ERROR1, __LINE__); + JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); + return JNI_FALSE; } ifn->CreateJavaVM = (CreateJavaVM_t) - dlsym(libjvm, "JNI_CreateJavaVM"); - if (ifn->CreateJavaVM == NULL) - goto error; + dlsym(libjvm, "JNI_CreateJavaVM"); + if (ifn->CreateJavaVM == NULL) { + JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); + return JNI_FALSE; + } ifn->GetDefaultJavaVMInitArgs = (GetDefaultJavaVMInitArgs_t) dlsym(libjvm, "JNI_GetDefaultJavaVMInitArgs"); - if (ifn->GetDefaultJavaVMInitArgs == NULL) - goto error; + if (ifn->GetDefaultJavaVMInitArgs == NULL) { + JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); + return JNI_FALSE; + } return JNI_TRUE; - -error: - JLI_ReportErrorMessage(DLL_ERROR2, jvmpath, dlerror()); - return JNI_FALSE; } /* @@ -575,7 +584,7 @@ char name[PATH_MAX + 2], *real; if ((JLI_StrLen(indir) + JLI_StrLen(cmd) + 1) > PATH_MAX) return 0; - sprintf(name, "%s%c%s", indir, FILE_SEPARATOR, cmd); + JLI_Snprintf(name, sizeof(name), "%s%c%s", indir, FILE_SEPARATOR, cmd); if (!ProgramExists(name)) return 0; real = JLI_MemAlloc(PATH_MAX + 2); if (!realpath(name, real)) @@ -622,7 +631,7 @@ else { /* relative path element */ char dir[2*PATH_MAX]; - sprintf(dir, "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), + JLI_Snprintf(dir, sizeof(dir), "%s%c%s", getcwd(cwdbuf, sizeof(cwdbuf)), FILE_SEPARATOR, s); result = Resolve(dir, program); } @@ -746,7 +755,7 @@ if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX) return (0); /* Silently reject "impossibly" long paths */ - sprintf(buffer, "%s/%s/bin/java", path, dir); + JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir); return ((access(buffer, X_OK) == 0) ? 1 : 0); }
--- a/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Jul 20 22:21:31 2010 -0700 @@ -1053,10 +1053,28 @@ return peer; } + private static Boolean sunAwtDisableGtkFileDialogs = null; + + /** + * Returns the value of "sun.awt.disableGtkFileDialogs" property. Default + * value is {@code false}. + */ + public synchronized static boolean getSunAwtDisableGtkFileDialogs() { + if (sunAwtDisableGtkFileDialogs == null) { + sunAwtDisableGtkFileDialogs = + getBooleanSystemProperty("sun.awt.disableGtkFileDialogs"); + } + return sunAwtDisableGtkFileDialogs.booleanValue(); + } + public FileDialogPeer createFileDialog(FileDialog target) { + FileDialogPeer peer = null; // The current GtkFileChooser is available from GTK+ 2.4 - FileDialogPeer peer = checkGtkVersion(2, 4, 0) ? new GtkFileDialogPeer( - target) : new XFileDialogPeer(target); + if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) { + peer = new GtkFileDialogPeer(target); + } else { + peer = new XFileDialogPeer(target); + } targetCreatedPeer(target, peer); return peer; } @@ -1201,14 +1219,6 @@ } } - static String getSystemProperty(final String name) { - return (String)AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - return System.getProperty(name); - } - }); - } - public PrintJob getPrintJob(final Frame frame, final String doctitle, final Properties props) {
--- a/src/solaris/classes/sun/awt/X11/XWindow.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/classes/sun/awt/X11/XWindow.java Tue Jul 20 22:21:31 2010 -0700 @@ -778,8 +778,8 @@ x, y, xbe.get_x_root(), xbe.get_y_root(), - clickCount,false,MouseWheelEvent.WHEEL_UNIT_SCROLL, - 3,button==4 ? -1 : 1); + 1,false,MouseWheelEvent.WHEEL_UNIT_SCROLL, + 3,button==4 ? -1*clickCount : 1*clickCount); postEventToEventQueue(mwe); } }
--- a/src/solaris/demo/jni/Poller/Poller.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/demo/jni/Poller/Poller.c Tue Jul 20 22:21:31 2010 -0700 @@ -160,10 +160,10 @@ return -1; } -#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" ## str) -#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" ## str) +#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" str) +#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" str) #define INTERRUPT_EXCEPTION(str) throwInterruptedIOException(env, \ - "Poller:" ## str) + "Poller:" str) jint addfd(JNIEnv *, ioevent_t *, jint, jshort); jint removefd(JNIEnv *, ioevent_t *, jint);
--- a/src/solaris/native/java/net/NetworkInterface.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/native/java/net/NetworkInterface.c Tue Jul 20 22:21:31 2010 -0700 @@ -23,6 +23,7 @@ * questions. */ + #include <errno.h> #include <strings.h> #include <netinet/in.h> @@ -33,23 +34,23 @@ #include <arpa/inet.h> #include <net/if.h> #include <net/if_arp.h> + #ifdef __solaris__ #include <sys/dlpi.h> #include <fcntl.h> #include <stropts.h> +#include <sys/sockio.h> #endif + #ifdef __linux__ #include <sys/ioctl.h> #include <bits/ioctls.h> #include <linux/sockios.h> #include <sys/utsname.h> #include <stdio.h> -#else -#include <sys/sockio.h> #endif #ifdef __linux__ -#define ifr_index ifr_ifindex #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6" #endif @@ -108,20 +109,41 @@ static jfieldID ni_ib4broadcastID; static jfieldID ni_ib4maskID; +/** Private methods declarations **/ static jobject createNetworkInterface(JNIEnv *env, netif *ifs); +static int getFlags0(JNIEnv *env, jstring ifname); -static netif *enumInterfaces(JNIEnv *env); -static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs); +static netif *enumInterfaces(JNIEnv *env); +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs); + #ifdef AF_INET6 -static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs); +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs); #endif -static netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, - int family, struct sockaddr *new_addrP, int new_addrlen, - short prefix); -static void freeif(netif *ifs); -static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname); -static short getSubnet(JNIEnv *env, const char *ifname); +static netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix); +static void freeif(netif *ifs); + +static int openSocket(JNIEnv *env, int proto); +static int openSocketWithFallback(JNIEnv *env, const char *ifname); + + +static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *name, struct sockaddr *brdcast_store); +static short getSubnet(JNIEnv *env, int sock, const char *ifname); +static int getIndex(int sock, const char *ifname); + +static int getFlags(JNIEnv *env, int sock, const char *ifname); +static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf); +static int getMTU(JNIEnv *env, int sock, const char *ifname); + + + +#ifdef __solaris__ +static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family); +static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf); +#endif + + +/******************* Java entry points *****************************/ /* * Class: java_net_NetworkInterface @@ -172,7 +194,7 @@ netif *ifs, *curr; jboolean isCopy; - const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + const char* name_utf; jobject obj = NULL; ifs = enumInterfaces(env); @@ -180,6 +202,8 @@ return NULL; } + name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + /* * Search the list of interface based on name */ @@ -253,12 +277,13 @@ (JNIEnv *env, jclass cls, jobject iaObj) { netif *ifs, *curr; + #ifdef AF_INET6 - int family = (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4? - AF_INET : AF_INET6; + int family = ( (*env)->GetIntField(env, iaObj, ni_iafamilyID) == IPv4 ) ? AF_INET : AF_INET6; #else - int family = AF_INET; + int family = AF_INET; #endif + jobject obj = NULL; jboolean match = JNI_FALSE; @@ -390,18 +415,169 @@ return netIFArr; } + +/* + * Class: java_net_NetworkInterface + * Method: isUp0 + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0(JNIEnv *env, jclass cls, jstring name, jint index) { + int ret = getFlags0(env, name); + return ((ret & IFF_UP) && (ret & IFF_RUNNING)) ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: java_net_NetworkInterface + * Method: isP2P0 + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0(JNIEnv *env, jclass cls, jstring name, jint index) { + int ret = getFlags0(env, name); + return (ret & IFF_POINTOPOINT) ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: java_net_NetworkInterface + * Method: isLoopback0 + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0(JNIEnv *env, jclass cls, jstring name, jint index) { + int ret = getFlags0(env, name); + return (ret & IFF_LOOPBACK) ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: java_net_NetworkInterface + * Method: supportsMulticast0 + * Signature: (Ljava/lang/String;I)Z + */ +JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0(JNIEnv *env, jclass cls, jstring name, jint index) { + int ret = getFlags0(env, name); + return (ret & IFF_MULTICAST) ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: java_net_NetworkInterface + * Method: getMacAddr0 + * Signature: ([bLjava/lang/String;I)[b + */ +JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) { + jint addr; + jbyte caddr[4]; + struct in_addr iaddr; + jbyteArray ret = NULL; + unsigned char mac[16]; + int len; + int sock; + jboolean isCopy; + const char* name_utf; + + name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + + if ((sock =openSocketWithFallback(env, name_utf)) < 0) { + (*env)->ReleaseStringUTFChars(env, name, name_utf); + return JNI_FALSE; + } + + + if (!IS_NULL(addrArray)) { + (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); + addr = ((caddr[0]<<24) & 0xff000000); + addr |= ((caddr[1] <<16) & 0xff0000); + addr |= ((caddr[2] <<8) & 0xff00); + addr |= (caddr[3] & 0xff); + iaddr.s_addr = htonl(addr); + len = getMacAddress(env, sock, name_utf, &iaddr, mac); + } else { + len = getMacAddress(env, sock, name_utf,NULL, mac); + } + if (len > 0) { + ret = (*env)->NewByteArray(env, len); + if (IS_NULL(ret)) { + /* we may have memory to free at the end of this */ + goto fexit; + } + (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac)); + } + fexit: + /* release the UTF string and interface list */ + (*env)->ReleaseStringUTFChars(env, name, name_utf); + + close(sock); + return ret; +} + +/* + * Class: java_net_NetworkInterface + * Method: getMTU0 + * Signature: ([bLjava/lang/String;I)I + */ + +JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) { + jboolean isCopy; + int ret = -1; + int sock; + const char* name_utf; + + name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + + if ((sock =openSocketWithFallback(env, name_utf)) < 0) { + (*env)->ReleaseStringUTFChars(env, name, name_utf); + return JNI_FALSE; + } + + ret = getMTU(env, sock, name_utf); + + (*env)->ReleaseStringUTFChars(env, name, name_utf); + + close(sock); + return ret; +} + +/*** Private methods definitions ****/ + +static int getFlags0(JNIEnv *env, jstring name) { + jboolean isCopy; + int ret, sock; + const char* name_utf; + + name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + + if ((sock = openSocketWithFallback(env, name_utf)) < 0) { + (*env)->ReleaseStringUTFChars(env, name, name_utf); + return -1; + } + + name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + + ret = getFlags(env, sock, name_utf); + + close(sock); + (*env)->ReleaseStringUTFChars(env, name, name_utf); + + if (ret < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed"); + return -1; + } + + return ret; +} + + + + /* * Create a NetworkInterface object, populate the name and index, and * populate the InetAddress array based on the IP addresses for this * interface. */ -jobject createNetworkInterface(JNIEnv *env, netif *ifs) -{ +jobject createNetworkInterface(JNIEnv *env, netif *ifs) { jobject netifObj; jobject name; jobjectArray addrArr; jobjectArray bindArr; jobjectArray childArr; + netaddr *addrs; jint addr_index, addr_count, bind_index; jint child_count, child_index; netaddr *addrP; @@ -441,7 +617,7 @@ bindArr = (*env)->NewObjectArray(env, addr_count, ni_ibcls, NULL); if (bindArr == NULL) { - return NULL; + return NULL; } addrP = ifs->addr; addr_index = 0; @@ -453,23 +629,22 @@ if (addrP->family == AF_INET) { iaObj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); if (iaObj) { - (*env)->SetIntField(env, iaObj, ni_iaaddressID, - htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr)); + (*env)->SetIntField(env, iaObj, ni_iaaddressID, htonl(((struct sockaddr_in*)addrP->addr)->sin_addr.s_addr)); } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj) { - (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); - if (addrP->brdcast) { - jobject ia2Obj = NULL; - ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); - if (ia2Obj) { - (*env)->SetIntField(env, ia2Obj, ni_iaaddressID, - htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr)); - (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj); - (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); - } - } - (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); + (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); + if (addrP->brdcast) { + jobject ia2Obj = NULL; + ia2Obj = (*env)->NewObject(env, ni_ia4cls, ni_ia4ctrID); + if (ia2Obj) { + (*env)->SetIntField(env, ia2Obj, ni_iaaddressID, + htonl(((struct sockaddr_in*)addrP->brdcast)->sin_addr.s_addr)); + (*env)->SetObjectField(env, ibObj, ni_ib4broadcastID, ia2Obj); + (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); + } + } + (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); } } @@ -483,14 +658,10 @@ return NULL; } (*env)->SetByteArrayRegion(env, ipaddress, 0, 16, - (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); -#ifdef __linux__ - if (!kernelIsV22()) { - scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; - } -#else + (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); + scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; -#endif + if (scope != 0) { /* zero is default value, no need to set */ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); @@ -500,9 +671,9 @@ } ibObj = (*env)->NewObject(env, ni_ibcls, ni_ibctrID); if (ibObj) { - (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); - (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); - (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); + (*env)->SetObjectField(env, ibObj, ni_ibaddressID, iaObj); + (*env)->SetShortField(env, ibObj, ni_ib4maskID, addrP->mask); + (*env)->SetObjectArrayElement(env, bindArr, bind_index++, ibObj); } } #endif @@ -521,13 +692,13 @@ child_count = 0; childP = ifs->childs; while (childP) { - child_count++; - childP = childP->next; + child_count++; + childP = childP->next; } childArr = (*env)->NewObjectArray(env, child_count, ni_class, NULL); if (childArr == NULL) { - return NULL; + return NULL; } /* @@ -539,7 +710,7 @@ while(childP) { tmp = createNetworkInterface(env, childP); if (tmp == NULL) { - return NULL; + return NULL; } (*env)->SetObjectField(env, tmp, ni_parentID, netifObj); (*env)->SetObjectArrayElement(env, childArr, child_index++, tmp); @@ -558,294 +729,56 @@ */ static netif *enumInterfaces(JNIEnv *env) { netif *ifs; + int sock; /* * Enumerate IPv4 addresses */ - ifs = enumIPv4Interfaces(env, NULL); - if (ifs == NULL) { - if ((*env)->ExceptionOccurred(env)) { - return NULL; - } + + sock = openSocket(env, AF_INET); + if (sock < 0 && (*env)->ExceptionOccurred(env)) { + return NULL; } + ifs = enumIPv4Interfaces(env, sock, NULL); + close(sock); + + if (ifs == NULL && (*env)->ExceptionOccurred(env)) { + return NULL; + } + + /* return partial list if exception occure in the middle of process ???*/ + /* * If IPv6 is available then enumerate IPv6 addresses. */ #ifdef AF_INET6 - if (ipv6_available()) { - ifs = enumIPv6Interfaces(env, ifs); + sock = openSocket(env, AF_INET6); + if (sock < 0 && (*env)->ExceptionOccurred(env)) { + freeif(ifs); + return NULL; + } + + ifs = enumIPv6Interfaces(env, sock, ifs); + close(sock); if ((*env)->ExceptionOccurred(env)) { freeif(ifs); return NULL; } - } #endif return ifs; } - -/* - * Enumerates and returns all IPv4 interfaces - */ -static netif *enumIPv4Interfaces(JNIEnv *env, netif *ifs) { - int sock; - struct ifconf ifc; - struct ifreq *ifreqP; - char *buf; - int numifs; - unsigned i; - unsigned bufsize; - - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - /* - * If EPROTONOSUPPORT is returned it means we don't have - * IPv4 support so don't throw an exception. - */ - if (errno != EPROTONOSUPPORT) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - } - return ifs; - } - -#ifdef __linux__ - /* need to do a dummy SIOCGIFCONF to determine the buffer size. - * SIOCGIFCOUNT doesn't work - */ - ifc.ifc_buf = NULL; - if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "ioctl SIOCGIFCONF failed"); - close(sock); - return ifs; - } - bufsize = ifc.ifc_len; -#else - if (ioctl(sock, SIOCGIFNUM, (char *)&numifs) < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "ioctl SIOCGIFNUM failed"); - close(sock); - return ifs; - } - bufsize = numifs * sizeof (struct ifreq); -#endif /* __linux__ */ - - buf = (char *)malloc(bufsize); - if (!buf) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - (void) close(sock); - return ifs; - } - ifc.ifc_len = bufsize; - ifc.ifc_buf = buf; - if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "ioctl SIOCGIFCONF failed"); - (void) close(sock); - (void) free(buf); - return ifs; - } - - /* - * Iterate through each interface - */ - ifreqP = ifc.ifc_req; - for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) { - int index; - struct ifreq if2; - - memset((char *)&if2, 0, sizeof(if2)); - strcpy(if2.ifr_name, ifreqP->ifr_name); - - /* - * Try to get the interface index - * (Not supported on Solaris 2.6 or 7) - */ - if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) >= 0) { - index = if2.ifr_index; - } else { - index = -1; - } - - /* - * Add to the list - */ - ifs = addif(env, ifs, ifreqP->ifr_name, index, AF_INET, - (struct sockaddr *)&(ifreqP->ifr_addr), - sizeof(struct sockaddr_in), 0); - - /* - * If an exception occurred then free the list - */ - if ((*env)->ExceptionOccurred(env)) { - close(sock); - free(buf); - freeif(ifs); - return NULL; - } - } - - /* - * Free socket and buffer - */ - close(sock); - free(buf); - return ifs; -} - - -#if defined(__solaris__) && defined(AF_INET6) -/* - * Enumerates and returns all IPv6 interfaces on Solaris - */ -static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) { - int sock; - struct lifconf ifc; - struct lifreq *ifr; - int n; - char *buf; - struct lifnum numifs; - unsigned bufsize; - - sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "Failed to create IPv6 socket"); - return ifs; - } - - /* - * Get the interface count - */ - numifs.lifn_family = AF_UNSPEC; - numifs.lifn_flags = 0; - if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "ioctl SIOCGLIFNUM failed"); - close(sock); - return ifs; - } - - /* - * Enumerate the interface configurations - */ - bufsize = numifs.lifn_count * sizeof (struct lifreq); - buf = (char *)malloc(bufsize); - if (!buf) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - (void) close(sock); - return ifs; - } - ifc.lifc_family = AF_UNSPEC; - ifc.lifc_flags = 0; - ifc.lifc_len = bufsize; - ifc.lifc_buf = buf; - if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { - NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", - "ioctl SIOCGLIFCONF failed"); - close(sock); - free(buf); - return ifs; - } - - /* - * Iterate through each interface - */ - ifr = ifc.lifc_req; - for (n=0; n<numifs.lifn_count; n++, ifr++) { - int index = -1; - struct lifreq if2; - - /* - * Ignore non-IPv6 addresses - */ - if (ifr->lifr_addr.ss_family != AF_INET6) { - continue; - } - - /* - * Get the index - */ - memset((char *)&if2, 0, sizeof(if2)); - strcpy(if2.lifr_name, ifr->lifr_name); - if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) >= 0) { - struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr); - index = if2.lifr_index; - s6->sin6_scope_id = index; - } - - /* add to the list */ - ifs = addif(env, ifs, ifr->lifr_name, index, AF_INET6, - (struct sockaddr *)&(ifr->lifr_addr), - sizeof(struct sockaddr_in6), (short) ifr->lifr_addrlen); - - /* - * If an exception occurred we return - */ - if ((*env)->ExceptionOccurred(env)) { - close(sock); - free(buf); - return ifs; - } - - } - - close(sock); - free(buf); - return ifs; - -} -#endif - - -#if defined(__linux__) && defined(AF_INET6) -/* - * Enumerates and returns all IPv6 interfaces on Linux - */ -static netif *enumIPv6Interfaces(JNIEnv *env, netif *ifs) { - FILE *f; - char addr6[40], devname[20]; - char addr6p[8][5]; - int plen, scope, dad_status, if_idx; - uint8_t ipv6addr[16]; - - if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { - while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", - addr6p[0], addr6p[1], addr6p[2], addr6p[3], - addr6p[4], addr6p[5], addr6p[6], addr6p[7], - &if_idx, &plen, &scope, &dad_status, devname) != EOF) { - struct sockaddr_in6 addr; - - sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", - addr6p[0], addr6p[1], addr6p[2], addr6p[3], - addr6p[4], addr6p[5], addr6p[6], addr6p[7]); - inet_pton(AF_INET6, addr6, ipv6addr); - - memset(&addr, 0, sizeof(struct sockaddr_in6)); - memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16); - addr.sin6_scope_id = if_idx; - - ifs = addif(env, ifs, devname, if_idx, AF_INET6, - (struct sockaddr *)&addr, - sizeof(struct sockaddr_in6), plen); - - /* - * If an exception occurred then return the list as is. - */ - if ((*env)->ExceptionOccurred(env)) { - fclose(f); - return ifs; - } - } - fclose(f); - } - return ifs; -} -#endif +#define CHECKED_MALLOC3(_pointer,_type,_size) \ + do{ \ + _pointer = (_type)malloc( _size ); \ + if (_pointer == NULL) { \ + JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); \ + return ifs; /* return untouched list */ \ + } \ + } while(0) /* @@ -853,52 +786,43 @@ */ void freeif(netif *ifs) { netif *currif = ifs; + netif *child = NULL; while (currif != NULL) { netaddr *addrP = currif->addr; while (addrP != NULL) { netaddr *next = addrP->next; - if (addrP->addr != NULL) - free(addrP->addr); - if (addrP->brdcast != NULL) - free(addrP->brdcast); free(addrP); addrP = next; - } - - free(currif->name); + } - /* - * Don't forget to free the sub-interfaces. - */ - if (currif->childs != NULL) { - freeif(currif->childs); - } + /* + * Don't forget to free the sub-interfaces. + */ + if (currif->childs != NULL) { + freeif(currif->childs); + } - ifs = currif->next; - free(currif); - currif = ifs; + ifs = currif->next; + free(currif); + currif = ifs; } } -/* - * Add an interface to the list. If known interface just link - * a new netaddr onto the list. If new interface create new - * netif structure. - */ -netif *addif(JNIEnv *env, netif *ifs, char *if_name, int index, int family, - struct sockaddr *new_addrP, int new_addrlen, short prefix) { - netif *currif = ifs, *parent; +netif *addif(JNIEnv *env, int sock, const char * if_name, netif *ifs, struct sockaddr* ifr_addrP, int family, short prefix) { + netif *currif = ifs, *parent; netaddr *addrP; -#ifdef LIFNAMSIZ - char name[LIFNAMSIZ]; - char vname[LIFNAMSIZ]; -#else - char name[IFNAMSIZ]; - char vname[IFNAMSIZ]; -#endif - char *unit; + + #ifdef __solaris__ + char name[LIFNAMSIZ], vname[LIFNAMSIZ]; + #else + char name[IFNAMSIZ], vname[IFNAMSIZ]; + #endif + + char *name_colonP; + int mask; int isVirtual = 0; + int addr_size; /* * If the interface name is a logical interface then we @@ -908,107 +832,63 @@ * logical interfaces. */ strcpy(name, if_name); + *vname = 0; /* * Create and populate the netaddr node. If allocation fails * return an un-updated list. */ - addrP = (netaddr *)malloc(sizeof(netaddr)); - if (addrP) { - addrP->addr = (struct sockaddr *)malloc(new_addrlen); - if (addrP->addr == NULL) { - free(addrP); - addrP = NULL; - } - } - if (addrP == NULL) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return ifs; /* return untouched list */ - } - memcpy(addrP->addr, new_addrP, new_addrlen); + /*Allocate for addr and brdcast at once*/ + +#ifdef AF_INET6 + addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6); +#else + addr_size = sizeof(struct sockaddr_in); +#endif + + CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr)+2*addr_size); + addrP->addr = (struct sockaddr *)( (char *) addrP+sizeof(netaddr) ); + memcpy(addrP->addr, ifr_addrP, addr_size); + addrP->family = family; - addrP->brdcast = NULL; addrP->mask = prefix; + addrP->next = 0; if (family == AF_INET) { /* * Deal with brodcast addr & subnet mask */ - addrP->brdcast = getBroadcast(env, name); - if (addrP->brdcast) { - addrP->mask = getSubnet(env, name); - } - } + struct sockaddr * brdcast_to = (struct sockaddr *) ((char *) addrP + sizeof(netaddr) + addr_size); + addrP->brdcast = getBroadcast(env, sock, name, brdcast_to ); - vname[0] = 0; - unit = strchr(name, ':'); - if (unit != NULL) { + if (addrP->brdcast && (mask = getSubnet(env, sock, name)) != -1) { + addrP->mask = mask; + } + } + + /** + * Deal with virtual interface with colon notaion e.g. eth0:1 + */ + name_colonP = strchr(name, ':'); + if (name_colonP != NULL) { /** * This is a virtual interface. If we are able to access the parent * we need to create a new entry if it doesn't exist yet *and* update * the 'parent' interface with the new records. */ - struct ifreq if2; - int sock; - int len; - - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return ifs; /* return untouched list */ - } - - len = unit - name; - if (len > 0) { - // temporarily use vname to hold the parent name of the interface - // instead of creating another buffer. - memcpy(&vname, name, len); - vname[len] = '\0'; - - memset((char *) &if2, 0, sizeof(if2)); - strcpy(if2.ifr_name, vname); - - if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) { - // Got access to parent, so create it if necessary. - strcpy(vname, name); - *unit = '\0'; - } else { -#if defined(__solaris__) && defined(AF_INET6) - struct lifreq lifr; - memset((char *) &lifr, 0, sizeof(lifr)); - strcpy(lifr.lifr_name, vname); - - /* Try with an IPv6 socket in case the interface has only IPv6 - * addresses assigned to it */ - close(sock); - sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); - - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return ifs; /* return untouched list */ - } - - if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) { - // Got access to parent, so create it if necessary. - strcpy(vname, name); - *unit = '\0'; - } else { + *name_colonP = 0; + if (getFlags(env,sock,name) < 0) { // failed to access parent interface do not create parent. // We are a virtual interface with no parent. isVirtual = 1; - vname[0] = 0; - } -#else - // failed to access parent interface do not create parent. - // We are a virtual interface with no parent. - isVirtual = 1; - vname[0] = 0; -#endif + *name_colonP = ':'; } - } - close(sock); + else{ + // Got access to parent, so create it if necessary. + // Save original name to vname and truncate name by ':' + memcpy(vname, name, sizeof(vname) ); + vname[name_colonP - name] = ':'; + } } /* @@ -1028,24 +908,15 @@ * insert it onto the list. */ if (currif == NULL) { - currif = (netif *)malloc(sizeof(netif)); - if (currif) { - currif->name = strdup(name); - if (currif->name == NULL) { - free(currif); - currif = NULL; - } - } - if (currif == NULL) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return ifs; - } - currif->index = index; - currif->addr = NULL; - currif->childs = NULL; - currif->virtual = isVirtual; - currif->next = ifs; - ifs = currif; + CHECKED_MALLOC3(currif, netif *, sizeof(netif)+IFNAMSIZ ); + currif->name = (char *) currif+sizeof(netif); + strcpy(currif->name, name); + currif->index = getIndex(sock, name); + currif->addr = NULL; + currif->childs = NULL; + currif->virtual = isVirtual; + currif->next = ifs; + ifs = currif; } /* @@ -1060,161 +931,251 @@ * Let's deal with the virtual interface now. */ if (vname[0]) { - netaddr *tmpaddr; + netaddr *tmpaddr; - currif = parent->childs; + currif = parent->childs; - while (currif != NULL) { - if (strcmp(vname, currif->name) == 0) { - break; - } - currif = currif->next; - } - if (currif == NULL) { - currif = (netif *)malloc(sizeof(netif)); - if (currif) { - currif->name = strdup(vname); - if (currif->name == NULL) { - free(currif); - currif = NULL; - } - } - if (currif == NULL) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return ifs; + while (currif != NULL) { + if (strcmp(vname, currif->name) == 0) { + break; + } + currif = currif->next; } - currif->index = index; - currif->addr = NULL; - /* Need to duplicate the addr entry? */ - currif->virtual = 1; - currif->childs = NULL; - currif->next = parent->childs; - parent->childs = currif; - } + + if (currif == NULL) { + CHECKED_MALLOC3(currif, netif *, sizeof(netif)+ IFNAMSIZ ); + currif->name = (char *) currif + sizeof(netif); + strcpy(currif->name, vname); + currif->index = getIndex(sock, vname); + currif->addr = NULL; + /* Need to duplicate the addr entry? */ + currif->virtual = 1; + currif->childs = NULL; + currif->next = parent->childs; + parent->childs = currif; + } - tmpaddr = (netaddr *) malloc(sizeof(netaddr)); - if (tmpaddr == NULL) { - JNU_ThrowOutOfMemoryError(env, "heap allocation failed"); - return ifs; - } - memcpy(tmpaddr, addrP, sizeof(netaddr)); - /** - * Let's duplicate the address and broadcast address structures - * if there are any. - */ - if (addrP->addr != NULL) { - tmpaddr->addr = malloc(new_addrlen); - if (tmpaddr->addr != NULL) - memcpy(tmpaddr->addr, addrP->addr, new_addrlen); - } - if (addrP->brdcast != NULL) { - tmpaddr->brdcast = malloc(new_addrlen); - if (tmpaddr->brdcast != NULL) - memcpy(tmpaddr->brdcast, addrP->brdcast, new_addrlen); - } - tmpaddr->next = currif->addr; - currif->addr = tmpaddr; + CHECKED_MALLOC3(tmpaddr, netaddr *, sizeof(netaddr)+2*addr_size); + memcpy(tmpaddr, addrP, sizeof(netaddr)); + if (addrP->addr != NULL) { + tmpaddr->addr = (struct sockaddr *) ( (char*)tmpaddr + sizeof(netaddr) ) ; + memcpy(tmpaddr->addr, addrP->addr, addr_size); + } + + if (addrP->brdcast != NULL) { + tmpaddr->brdcast = (struct sockaddr *) ((char *) tmpaddr + sizeof(netaddr)+addr_size); + memcpy(tmpaddr->brdcast, addrP->brdcast, addr_size); + } + + tmpaddr->next = currif->addr; + currif->addr = tmpaddr; } return ifs; } -/** - * Get flags from a NetworkInterface. +/* Open socket for further ioct calls + * proto is AF_INET/AF_INET6 */ -static short getFlags(JNIEnv *env, jstring name) { - int sock; - struct ifreq if2; - jboolean isCopy; - const char* name_utf; - short ret = -1; +static int openSocket(JNIEnv *env, int proto){ + int sock; + + if ((sock = JVM_Socket(proto, SOCK_DGRAM, 0)) < 0) { + /* + * If EPROTONOSUPPORT is returned it means we don't have + * support for this proto so don't throw an exception. + */ + if (errno != EPROTONOSUPPORT) { + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "Socket creation failed"); + } + return -1; + } - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return -1; - } + return sock; +} + + +/** Linux **/ +#ifdef __linux__ +/* Open socket for further ioct calls, try v4 socket first and + * if it falls return v6 socket + */ + +#ifdef AF_INET6 +static int openSocketWithFallback(JNIEnv *env, const char *ifname){ + int sock; + struct ifreq if2; - name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); - memset((char *) &if2, 0, sizeof(if2)); - strcpy(if2.ifr_name, name_utf); + if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if (errno == EPROTONOSUPPORT){ + if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){ + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); + return -1; + } + } + else{ // errno is not NOSUPPORT + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); + return -1; + } + } + + /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type + of address of an interface */ + + return sock; +} + +#else +static int openSocketWithFallback(JNIEnv *env, const char *ifname){ + return openSocket(env,AF_INET); +} +#endif - if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) { - ret = if2.ifr_flags; - } else { -#if defined(__solaris__) && defined(AF_INET6) - /* Try with an IPv6 socket in case the interface has only IPv6 addresses assigned to it */ - struct lifreq lifr; +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { + struct ifconf ifc; + struct ifreq *ifreqP; + char *buf; + int numifs; + unsigned i; + - close(sock); - sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); + /* need to do a dummy SIOCGIFCONF to determine the buffer size. + * SIOCGIFCOUNT doesn't work + */ + ifc.ifc_buf = NULL; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); + return ifs; + } - if (sock < 0) { - (*env)->ReleaseStringUTFChars(env, name, name_utf); - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return -1; + CHECKED_MALLOC3(buf,char *, ifc.ifc_len); + + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGIFCONF failed"); + (void) free(buf); + return ifs; } - memset((caddr_t)&lifr, 0, sizeof(lifr)); - strcpy((caddr_t)&(lifr.lifr_name), name_utf); + /* + * Iterate through each interface + */ + ifreqP = ifc.ifc_req; + for (i=0; i<ifc.ifc_len/sizeof (struct ifreq); i++, ifreqP++) { + /* + * Add to the list + */ + ifs = addif(env, sock, ifreqP->ifr_name, ifs, (struct sockaddr *) & (ifreqP->ifr_addr), AF_INET, 0); - if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) >= 0) { - ret = lifr.lifr_flags; - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); + /* + * If an exception occurred then free the list + */ + if ((*env)->ExceptionOccurred(env)) { + free(buf); + freeif(ifs); + return NULL; + } } -#else - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); + + /* + * Free socket and buffer + */ + free(buf); + return ifs; +} + + +/* + * Enumerates and returns all IPv6 interfaces on Linux + */ + +#ifdef AF_INET6 +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { + FILE *f; + char addr6[40], devname[20]; + char addr6p[8][5]; + int plen, scope, dad_status, if_idx; + uint8_t ipv6addr[16]; + + if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) { + while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n", + addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7], + &if_idx, &plen, &scope, &dad_status, devname) != EOF) { + + struct netif *ifs_ptr = NULL; + struct netif *last_ptr = NULL; + struct sockaddr_in6 addr; + + sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", + addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4], addr6p[5], addr6p[6], addr6p[7]); + inet_pton(AF_INET6, addr6, ipv6addr); + + memset(&addr, 0, sizeof(struct sockaddr_in6)); + memcpy((void*)addr.sin6_addr.s6_addr, (const void*)ipv6addr, 16); + + addr.sin6_scope_id = if_idx; + + ifs = addif(env, sock, devname, ifs, (struct sockaddr *)&addr, AF_INET6, plen); + + + /* + * If an exception occurred then return the list as is. + */ + if ((*env)->ExceptionOccurred(env)) { + fclose(f); + return ifs; + } + } + fclose(f); + } + return ifs; +} #endif - } - close(sock); - /* release the UTF string and interface list */ - (*env)->ReleaseStringUTFChars(env, name, name_utf); + - return ret; +static int getIndex(int sock, const char *name){ + /* + * Try to get the interface index + * (Not supported on Solaris 2.6 or 7) + */ + struct ifreq if2; + strcpy(if2.ifr_name, name); + + if (ioctl(sock, SIOCGIFINDEX, (char *)&if2) < 0) { + return -1; + } + + return if2.ifr_ifindex; } /** * Returns the IPv4 broadcast address of a named interface, if it exists. * Returns 0 if it doesn't have one. */ -static struct sockaddr *getBroadcast(JNIEnv *env, const char *ifname) { - int sock; +static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) { struct sockaddr *ret = NULL; struct ifreq if2; - short flag = 0; - - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return ret; - } memset((char *) &if2, 0, sizeof(if2)); strcpy(if2.ifr_name, ifname); + /* Let's make sure the interface does have a broadcast address */ - if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) >= 0) { - flag = if2.ifr_flags; - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); + if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFFLAGS failed"); + return ret; } - if (flag & IFF_BROADCAST) { - /* It does, let's retrieve it*/ - if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) >= 0) { - ret = (struct sockaddr*) malloc(sizeof(struct sockaddr)); + + if (if2.ifr_flags & IFF_BROADCAST) { + /* It does, let's retrieve it*/ + if (ioctl(sock, SIOCGIFBRDADDR, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFBRDADDR failed"); + return ret; + } + + ret = brdcast_store; memcpy(ret, &if2.ifr_broadaddr, sizeof(struct sockaddr)); - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - } } - close(sock); + return ret; } @@ -1222,39 +1183,314 @@ * Returns the IPv4 subnet prefix length (aka subnet mask) for the named * interface, if it has one, otherwise return -1. */ -static short getSubnet(JNIEnv *env, const char *ifname) { - int sock; - unsigned int mask; - short ret; - struct ifreq if2; +static short getSubnet(JNIEnv *env, int sock, const char *ifname) { + unsigned int mask; + short ret; + struct ifreq if2; + + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.ifr_name, ifname); + + if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFNETMASK failed"); + return -1; + } + + mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr); + ret = 0; + while (mask) { + mask <<= 1; + ret++; + } + + return ret; +} + +/** + * Get the Hardware address (usually MAC address) for the named interface. + * return puts the data in buf, and returns the length, in byte, of the + * MAC address. Returns -1 if there is no hardware address on that interface. + */ +static int getMacAddress(JNIEnv *env, int sock, const char* ifname, const struct in_addr* addr, unsigned char *buf) { + static struct ifreq ifr; + int i; - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); + strcpy(ifr.ifr_name, ifname); + if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFHWADDR failed"); + return -1; + } + + memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); + + /* + * All bytes to 0 means no hardware address. + */ + + for (i = 0; i < IFHWADDRLEN; i++) { + if (buf[i] != 0) + return IFHWADDRLEN; + } + return -1; - } +} + +static int getMTU(JNIEnv *env, int sock, const char *ifname) { + struct ifreq if2; + + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.ifr_name, ifname); + + if (ioctl(sock, SIOCGIFMTU, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGIFMTU failed"); + return -1; + } + + return if2.ifr_mtu; +} + +static int getFlags(JNIEnv *env, int sock, const char *ifname) { + struct ifreq if2; + int ret = -1; memset((char *) &if2, 0, sizeof(if2)); strcpy(if2.ifr_name, ifname); - if (ioctl(sock, SIOCGIFNETMASK, (char *)&if2) >= 0) { - mask = ntohl(((struct sockaddr_in*)&(if2.ifr_addr))->sin_addr.s_addr); - ret = 0; - while (mask) { - mask <<= 1; - ret++; + + if (ioctl(sock, SIOCGIFFLAGS, (char *)&if2) < 0){ + return -1; + } + + return if2.ifr_flags; +} + +#endif + +/** Solaris **/ +#ifdef __solaris__ +/* Open socket for further ioct calls, try v4 socket first and + * if it falls return v6 socket + */ + +#ifdef AF_INET6 +static int openSocketWithFallback(JNIEnv *env, const char *ifname){ + int sock, alreadyV6 = 0; + struct lifreq if2; + + if ((sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if (errno == EPROTONOSUPPORT){ + if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){ + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); + return -1; + } + + alreadyV6=1; + } + else{ // errno is not NOSUPPORT + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV4 Socket creation failed"); + return -1; + } + } + + /** + * Solaris requires that we have IPv6 socket to query an + * interface without IPv4 address - check it here + * POSIX 1 require the kernell to return ENOTTY if the call is + * unappropriate for device e.g. NETMASK for device having IPv6 + * only address but not all devices follows the standart so + * fallback on any error. It's not an ecology friendly but more + * reliable. + */ + + if (! alreadyV6 ){ + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.lifr_name, ifname); + if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) { + close(sock); + if ( (sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0)) < 0 ){ + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "IPV6 Socket creation failed"); + return -1; + } + } } - close(sock); - return ret; - } - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - close(sock); - return -1; + + return sock; +} + +#else +static int openSocketWithFallback(JNIEnv *env, const char *ifname){ + return openSocket(env,AF_INET); +} +#endif + +/* + * Enumerates and returns all IPv4 interfaces + * (linux verison) + */ + +static netif *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs) { + return enumIPvXInterfaces(env,sock, ifs, AF_INET); } -#ifdef __solaris__ -#define DEV_PREFIX "/dev/" +#ifdef AF_INET6 +static netif *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs) { + return enumIPvXInterfaces(env,sock, ifs, AF_INET6); +} +#endif + +/* + Enumerates and returns all interfaces on Solaris + use the same code for IPv4 and IPv6 + */ +static netif *enumIPvXInterfaces(JNIEnv *env, int sock, netif *ifs, int family) { + struct lifconf ifc; + struct lifreq *ifr; + int n; + char *buf; + struct lifnum numifs; + unsigned bufsize; + + /* + * Get the interface count + */ + numifs.lifn_family = family; + numifs.lifn_flags = 0; + if (ioctl(sock, SIOCGLIFNUM, (char *)&numifs) < 0) { + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFNUM failed"); + return ifs; + } + + /* + * Enumerate the interface configurations + */ + bufsize = numifs.lifn_count * sizeof (struct lifreq); + CHECKED_MALLOC3(buf, char *, bufsize); + + ifc.lifc_family = family; + ifc.lifc_flags = 0; + ifc.lifc_len = bufsize; + ifc.lifc_buf = buf; + if (ioctl(sock, SIOCGLIFCONF, (char *)&ifc) < 0) { + NET_ThrowByNameWithLastError(env , JNU_JAVANETPKG "SocketException", "ioctl SIOCGLIFCONF failed"); + free(buf); + return ifs; + } + + /* + * Iterate through each interface + */ + ifr = ifc.lifc_req; + for (n=0; n<numifs.lifn_count; n++, ifr++) { + int index = -1; + struct lifreq if2; + + /* + * Ignore either IPv4 or IPv6 addresses + */ + if (ifr->lifr_addr.ss_family != family) { + continue; + } + +#ifdef AF_INET6 + if (ifr->lifr_addr.ss_family == AF_INET6) { + struct sockaddr_in6 *s6= (struct sockaddr_in6 *)&(ifr->lifr_addr); + s6->sin6_scope_id = getIndex(sock, ifr->lifr_name); + } +#endif + + /* add to the list */ + ifs = addif(env, sock,ifr->lifr_name, ifs, (struct sockaddr *)&(ifr->lifr_addr),family, (short) ifr->lifr_addrlen); + + /* + * If an exception occurred we return immediately + */ + if ((*env)->ExceptionOccurred(env)) { + free(buf); + return ifs; + } + + } + + free(buf); + return ifs; +} + +static int getIndex(int sock, const char *name){ + /* + * Try to get the interface index + * (Not supported on Solaris 2.6 or 7) + */ + struct lifreq if2; + strcpy(if2.lifr_name, name); + + if (ioctl(sock, SIOCGLIFINDEX, (char *)&if2) < 0) { + return -1; + } + + return if2.lifr_index; +} + +/** + * Returns the IPv4 broadcast address of a named interface, if it exists. + * Returns 0 if it doesn't have one. + */ +static struct sockaddr *getBroadcast(JNIEnv *env, int sock, const char *ifname, struct sockaddr *brdcast_store) { + struct sockaddr *ret = NULL; + struct lifreq if2; + + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.lifr_name, ifname); + + /* Let's make sure the interface does have a broadcast address */ + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed"); + return ret; + } + + if (if2.lifr_flags & IFF_BROADCAST) { + /* It does, let's retrieve it*/ + if (ioctl(sock, SIOCGLIFBRDADDR, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFBRDADDR failed"); + return ret; + } + + ret = brdcast_store; + memcpy(ret, &if2.lifr_broadaddr, sizeof(struct sockaddr)); + } + + return ret; +} + +/** + * Returns the IPv4 subnet prefix length (aka subnet mask) for the named + * interface, if it has one, otherwise return -1. + */ +static short getSubnet(JNIEnv *env, int sock, const char *ifname) { + unsigned int mask; + short ret; + struct lifreq if2; + + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.lifr_name, ifname); + + if (ioctl(sock, SIOCGLIFNETMASK, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFNETMASK failed"); + return -1; + } + + mask = ntohl(((struct sockaddr_in*)&(if2.lifr_addr))->sin_addr.s_addr); + ret = 0; + + while (mask) { + mask <<= 1; + ret++; + } + + return ret; +} + + + +#define DEV_PREFIX "/dev/" /** * Solaris specific DLPI code to get hardware address from a device. @@ -1262,306 +1498,147 @@ * privileges (i.e. be root). */ static int getMacFromDevice(JNIEnv *env, const char* ifname, unsigned char* retbuf) { - char style1dev[MAXPATHLEN]; - int fd; - dl_phys_addr_req_t dlpareq; - dl_phys_addr_ack_t *dlpaack; - struct strbuf msg; - char buf[128]; - int flags = 0; + char style1dev[MAXPATHLEN]; + int fd; + dl_phys_addr_req_t dlpareq; + dl_phys_addr_ack_t *dlpaack; + struct strbuf msg; + char buf[128]; + int flags = 0; + + /** + * Device is in /dev + * e.g.: /dev/bge0 + */ + strcpy(style1dev, DEV_PREFIX); + strcat(style1dev, ifname); + if ((fd = open(style1dev, O_RDWR)) < 0) { + /* + * Can't open it. We probably are missing the privilege. + * We'll have to try something else + */ + return 0; + } + + dlpareq.dl_primitive = DL_PHYS_ADDR_REQ; + dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR; - /** - * Device is in /dev - * e.g.: /dev/bge0 - */ - strcpy(style1dev, DEV_PREFIX); - strcat(style1dev, ifname); - if ((fd = open(style1dev, O_RDWR)) == -1) { - /* - * Can't open it. We probably are missing the privilege. - * We'll have to try something else - */ - return 0; - } - dlpareq.dl_primitive = DL_PHYS_ADDR_REQ; - dlpareq.dl_addr_type = DL_CURR_PHYS_ADDR; - msg.buf = (char *)&dlpareq; - msg.len = DL_PHYS_ADDR_REQ_SIZE; - if (putmsg(fd, &msg, NULL, 0) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "putmsg failed"); - return -1; - } - dlpaack = (dl_phys_addr_ack_t *)buf; - msg.buf = (char *)buf; - msg.len = 0; - msg.maxlen = sizeof (buf); - if (getmsg(fd, &msg, NULL, &flags) < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "getmsg failed"); - return -1; - } - if (msg.len < DL_PHYS_ADDR_ACK_SIZE || - dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) { - JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", - "Couldn't obtain phys addr\n"); - return -1; - } + msg.buf = (char *)&dlpareq; + msg.len = DL_PHYS_ADDR_REQ_SIZE; + + if (putmsg(fd, &msg, NULL, 0) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "putmsg failed"); + return -1; + } + + dlpaack = (dl_phys_addr_ack_t *)buf; - memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length); - return dlpaack->dl_addr_length; + msg.buf = (char *)buf; + msg.len = 0; + msg.maxlen = sizeof (buf); + if (getmsg(fd, &msg, NULL, &flags) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "getmsg failed"); + return -1; + } + + if (msg.len < DL_PHYS_ADDR_ACK_SIZE || dlpaack->dl_primitive != DL_PHYS_ADDR_ACK) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Couldn't obtain phys addr\n"); + return -1; + } + + memcpy(retbuf, &buf[dlpaack->dl_addr_offset], dlpaack->dl_addr_length); + return dlpaack->dl_addr_length; } -#endif /** * Get the Hardware address (usually MAC address) for the named interface. * return puts the data in buf, and returns the length, in byte, of the * MAC address. Returns -1 if there is no hardware address on that interface. */ -int getMacAddress(JNIEnv *env, const struct in_addr* addr, const char* ifname, - unsigned char *buf) { - int sock; -#ifdef __linux__ - static struct ifreq ifr; - int i; +static int getMacAddress(JNIEnv *env, int sock, const char *ifname, const struct in_addr* addr, unsigned char *buf) { + struct arpreq arpreq; + struct sockaddr_in* sin; + struct sockaddr_in ipAddr; + int len, i; + + /** + * On Solaris we have to use DLPI, but it will only work if we have + * privileged access (i.e. root). If that fails, we try a lookup + * in the ARP table, which requires an IPv4 address. + */ + if ((len = getMacFromDevice(env, ifname, buf)) == 0) { + /*DLPI failed - trying to do arp lookup*/ + + if (addr == NULL) { + /** + * No IPv4 address for that interface, so can't do an ARP lookup. + */ + return -1; + } - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); + len = 6; //??? + + sin = (struct sockaddr_in *) &arpreq.arp_pa; + memset((char *) &arpreq, 0, sizeof(struct arpreq)); + ipAddr.sin_port = 0; + ipAddr.sin_family = AF_INET; + memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr)); + memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); + arpreq.arp_flags= ATF_PUBL; - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return -1; + if (ioctl(sock, SIOCGARP, &arpreq) < 0) { + if (errno != ENXIO) { + // "No such device or address" means no hardware address, so it's + // normal don't throw an exception + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL failed"); + return -1; + } + } + + memcpy(buf, &arpreq.arp_ha.sa_data[0], len ); } - strcpy(ifr.ifr_name, ifname); - - if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { - fprintf(stderr, "SIOCIFHWADDR: %s\n", - strerror(errno)); - close(sock); - return -1; - } - memcpy(buf, &ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); - close(sock); - for (i = 0; i < IFHWADDRLEN; i++) { - if (buf[i] != 0) - return IFHWADDRLEN; - } - /* - * All bytes to 0 means no hardware address. - */ - return -1; -#else - struct arpreq arpreq; - struct sockaddr_in* sin; - struct sockaddr_in ipAddr; - int len; - - /** - * On Solaris we have to use DLPI, but it will only work if we have - * privileged access (i.e. root). If that fails, we try a lookup - * in the ARP table, which requires an IPv4 address. - */ - if ((len = getMacFromDevice(env, ifname, buf)) > 0) { - return len; - } - if (addr == NULL) { - /** - * No IPv4 address for that interface, so can't do an ARP lookup. + /* + * All bytes to 0 means no hardware address. */ - return -1; - } - sin = (struct sockaddr_in *) &arpreq.arp_pa; - memset((char *) &arpreq, 0, sizeof(struct arpreq)); - ipAddr.sin_port = 0; - ipAddr.sin_family = AF_INET; - memcpy(&ipAddr.sin_addr, addr, sizeof(struct in_addr)); - memcpy(&arpreq.arp_pa, &ipAddr, sizeof(struct sockaddr_in)); - arpreq.arp_flags= ATF_PUBL; - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return -1; - } - if (ioctl(sock, SIOCGARP, &arpreq) >= 0) { - close(sock); - memcpy(buf, &arpreq.arp_ha.sa_data[0], 6); - return 6; - } - - if (errno != ENXIO) { - // "No such device or address" means no hardware address, so it's - // normal don't throw an exception - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - } - close(sock); -#endif - return -1; -} - -/* - * Class: java_net_NetworkInterface - * Method: isUp0 - * Signature: (Ljava/lang/String;I)Z - */ -JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isUp0 - (JNIEnv *env, jclass cls, jstring name, jint index) { - short val; + for (i = 0; i < len; i++) { + if (buf[i] != 0) + return len; + } - val = getFlags(env, name); - if ( (val & IFF_UP) && (val & IFF_RUNNING)) - return JNI_TRUE; - return JNI_FALSE; -} - -/* - * Class: java_net_NetworkInterface - * Method: isP2P0 - * Signature: (Ljava/lang/String;I)Z - */ -JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isP2P0 - (JNIEnv *env, jclass cls, jstring name, jint index) { - if (getFlags(env, name) & IFF_POINTOPOINT) - return JNI_TRUE; - return JNI_FALSE; -} - -/* - * Class: java_net_NetworkInterface - * Method: isLoopback0 - * Signature: (Ljava/lang/String;I)Z - */ -JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0 - (JNIEnv *env, jclass cls, jstring name, jint index) { - if (getFlags(env, name) & IFF_LOOPBACK) - return JNI_TRUE; - return JNI_FALSE; + return -1; } -/* - * Class: java_net_NetworkInterface - * Method: supportsMulticast0 - * Signature: (Ljava/lang/String;I)Z - */ -JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_supportsMulticast0 -(JNIEnv *env, jclass cls, jstring name, jint index) { - short val; +static int getMTU(JNIEnv *env, int sock, const char *ifname) { + struct lifreq if2; - val = getFlags(env, name); - if (val & IFF_MULTICAST) - return JNI_TRUE; - return JNI_FALSE; -} + memset((char *) &if2, 0, sizeof(if2)); + strcpy(if2.lifr_name, ifname); -/* - * Class: java_net_NetworkInterface - * Method: getMacAddr0 - * Signature: ([bLjava/lang/String;I)[b - */ -JNIEXPORT jbyteArray JNICALL Java_java_net_NetworkInterface_getMacAddr0(JNIEnv *env, jclass class, jbyteArray addrArray, jstring name, jint index) { - jint addr; - jbyte caddr[4]; - struct in_addr iaddr; - jbyteArray ret = NULL; - unsigned char mac[16]; - int len; - jboolean isCopy; - const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); + if (ioctl(sock, SIOCGLIFMTU, (char *)&if2) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFMTU failed"); + return -1; + } - if (!IS_NULL(addrArray)) { - (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr); - addr = ((caddr[0]<<24) & 0xff000000); - addr |= ((caddr[1] <<16) & 0xff0000); - addr |= ((caddr[2] <<8) & 0xff00); - addr |= (caddr[3] & 0xff); - iaddr.s_addr = htonl(addr); - len = getMacAddress(env, &iaddr, name_utf, mac); - } else { - len = getMacAddress(env, NULL, name_utf, mac); - } - if (len > 0) { - ret = (*env)->NewByteArray(env, len); - if (IS_NULL(ret)) { - /* we may have memory to free at the end of this */ - goto fexit; - } - (*env)->SetByteArrayRegion(env, ret, 0, len, (jbyte *) (mac)); - } - fexit: - /* release the UTF string and interface list */ - (*env)->ReleaseStringUTFChars(env, name, name_utf); - return ret; + return if2.lifr_mtu; } -/* - * Class: java_net_NetworkInterface - * Method: getMTU0 - * Signature: ([bLjava/lang/String;I)I - */ -JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0(JNIEnv *env, jclass class, jstring name, jint index) { - jboolean isCopy; - int sock; - struct ifreq if2; - int ret = -1; - const char* name_utf = (*env)->GetStringUTFChars(env, name, &isCopy); - - sock = JVM_Socket(AF_INET, SOCK_DGRAM, 0); - if (sock < 0) { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - } else { - -#ifdef __linux__ - memset((char *) &if2, 0, sizeof(if2)); - strcpy(if2.ifr_name, name_utf); +static int getFlags(JNIEnv *env, int sock, const char *ifname) { + struct lifreq lifr; + memset((caddr_t)&lifr, 0, sizeof(lifr)); + strcpy((caddr_t)&(lifr.lifr_name), ifname); - if (ioctl(sock, SIOCGIFMTU, (char *)&if2) >= 0) { - ret= if2.ifr_mtu; - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - } -#else /* Solaris */ - struct lifreq lifr; - memset((caddr_t)&lifr, 0, sizeof(lifr)); - strcpy((caddr_t)&(lifr.lifr_name), name_utf); - if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) { - ret = lifr.lifr_mtu; -#ifdef AF_INET6 - } else { - /* Try wIth an IPv6 socket in case the interface has only IPv6 addresses assigned to it */ - close(sock); - sock = JVM_Socket(AF_INET6, SOCK_DGRAM, 0); + if (ioctl(sock, SIOCGLIFFLAGS, (char *)&lifr) < 0) { + NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", "IOCTL SIOCGLIFFLAGS failed"); + return -1; + } - if (sock < 0) { - (*env)->ReleaseStringUTFChars(env, name, name_utf); - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "Socket creation failed"); - return -1; - } + return lifr.lifr_flags; +} + - if (ioctl(sock, SIOCGLIFMTU, (caddr_t)&lifr) >= 0) { - ret = lifr.lifr_mtu; - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - } - } -#else - } else { - NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", - "IOCTL failed"); - } #endif -#endif - close(sock); - } - /* release the UTF string and interface list */ - (*env)->ReleaseStringUTFChars(env, name, name_utf); - return ret; -} + +
--- a/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/native/sun/awt/sun_awt_X11_GtkFileDialogPeer.c Tue Jul 20 22:21:31 2010 -0700 @@ -42,6 +42,29 @@ filename); } +static void quit(gboolean isSignalHandler) +{ + if (dialog != NULL) + { + // Callbacks from GTK signals are made within the GTK lock + // So, within a signal handler there is no need to call + // gdk_threads_enter() / fp_gdk_threads_leave() + if (!isSignalHandler) { + fp_gdk_threads_enter(); + } + + fp_gtk_widget_hide (dialog); + fp_gtk_widget_destroy (dialog); + + fp_gtk_main_quit (); + dialog = NULL; + + if (!isSignalHandler) { + fp_gdk_threads_leave(); + } + } +} + /* * Class: sun_awt_X11_GtkFileDialogPeer * Method: quit @@ -50,18 +73,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_GtkFileDialogPeer_quit (JNIEnv * env, jobject jpeer) { - if (dialog != NULL) - { - fp_gdk_threads_enter(); - - fp_gtk_widget_hide (dialog); - fp_gtk_widget_destroy (dialog); - - fp_gtk_main_quit (); - dialog = NULL; - - fp_gdk_threads_leave(); - } + quit(FALSE); } /** @@ -147,7 +159,7 @@ jfilenames); fp_g_free(current_folder); - Java_sun_awt_X11_GtkFileDialogPeer_quit(NULL, NULL); + quit(TRUE); } /*
--- a/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/native/sun/java2d/opengl/GLXSurfaceData.c Tue Jul 20 22:21:31 2010 -0700 @@ -65,6 +65,11 @@ J2dTraceLn(J2D_TRACE_INFO, "GLXSurfaceData_initOps"); + if (oglsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } + if (glxsdo == NULL) { JNU_ThrowOutOfMemoryError(env, "creating native GLX ops"); return;
--- a/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/solaris/native/sun/java2d/x11/X11SurfaceData.c Tue Jul 20 22:21:31 2010 -0700 @@ -253,6 +253,10 @@ { #ifndef HEADLESS X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps)); + if (xsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } xsdo->sdOps.Lock = X11SD_Lock; xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo; xsdo->sdOps.Unlock = X11SD_Unlock;
--- a/src/windows/bin/java_md.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/windows/bin/java_md.c Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,26 +80,22 @@ * */ void -CreateExecutionEnvironment(int *_argc, - char ***_argv, - char jrepath[], - jint so_jrepath, - char jvmpath[], - jint so_jvmpath, - char **original_argv) { +CreateExecutionEnvironment(int *pargc, char ***pargv, + char *jrepath, jint so_jrepath, + char *jvmpath, jint so_jvmpath) { char * jvmtype; int i = 0; - char** pargv = *_argv; int running = CURRENT_DATA_MODEL; int wanted = running; - for (i = 0; i < *_argc ; i++) { - if (JLI_StrCmp(pargv[i], "-J-d64") == 0 || JLI_StrCmp(pargv[i], "-d64") == 0) { + char** argv = *pargv; + for (i = 0; i < *pargc ; i++) { + if (JLI_StrCmp(argv[i], "-J-d64") == 0 || JLI_StrCmp(argv[i], "-d64") == 0) { wanted = 64; continue; } - if (JLI_StrCmp(pargv[i], "-J-d32") == 0 || JLI_StrCmp(pargv[i], "-d32") == 0) { + if (JLI_StrCmp(argv[i], "-J-d32") == 0 || JLI_StrCmp(argv[i], "-d32") == 0) { wanted = 32; continue; } @@ -123,7 +119,12 @@ JLI_ReportErrorMessage(CFG_ERROR7); exit(1); } - jvmtype = CheckJvmType(_argc, _argv, JNI_FALSE); + + jvmtype = CheckJvmType(pargc, pargv, JNI_FALSE); + if (JLI_StrCmp(jvmtype, "ERROR") == 0) { + JLI_ReportErrorMessage(CFG_ERROR9); + exit(4); + } jvmpath[0] = '\0'; if (!GetJVMPath(jrepath, jvmtype, jvmpath, so_jvmpath)) { @@ -131,7 +132,6 @@ exit(4); } /* If we got here, jvmpath has been correctly initialized. */ - } @@ -203,19 +203,21 @@ PREJVMSTART PreJVMStart; struct stat s; + /* Make sure the jrepath contains something */ + if (jrepath[0] == NULL) { + return; + } /* 32 bit windows only please */ - if (strcmp(GetArch(), "i386") != 0 ) { + if (JLI_StrCmp(GetArch(), "i386") != 0 ) { return; } /* Does our bundle directory exist ? */ - strcpy(tmpbuf, jrepath); - strcat(tmpbuf, "\\lib\\bundles"); + JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\lib\\bundles", jrepath); if (stat(tmpbuf, &s) != 0) { return; } /* Does our jkernel dll exist ? */ - strcpy(tmpbuf, jrepath); - strcat(tmpbuf, "\\bin\\jkernel.dll"); + JLI_Snprintf(tmpbuf, sizeof(tmpbuf), "%s\\bin\\jkernel.dll", jrepath); if (stat(tmpbuf, &s) != 0) { return; } @@ -249,30 +251,30 @@ if (GetApplicationHome(path, pathsize)) { /* Is JRE co-located with the application? */ - sprintf(javadll, "%s\\bin\\" JAVA_DLL, path); + JLI_Snprintf(javadll, sizeof(javadll), "%s\\bin\\" JAVA_DLL, path); if (stat(javadll, &s) == 0) { - goto found; + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; } /* Does this app ship a private JRE in <apphome>\jre directory? */ - sprintf(javadll, "%s\\jre\\bin\\" JAVA_DLL, path); + JLI_Snprintf(javadll, sizeof (javadll), "%s\\jre\\bin\\" JAVA_DLL, path); if (stat(javadll, &s) == 0) { JLI_StrCat(path, "\\jre"); - goto found; + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; } } /* Look for a public JRE on this machine. */ if (GetPublicJREHome(path, pathsize)) { - goto found; + JLI_TraceLauncher("JRE path is %s\n", path); + return JNI_TRUE; } JLI_ReportErrorMessage(JRE_ERROR8 JAVA_DLL); return JNI_FALSE; - found: - JLI_TraceLauncher("JRE path is %s\n", path); - return JNI_TRUE; } /* @@ -286,9 +288,9 @@ { struct stat s; if (JLI_StrChr(jvmtype, '/') || JLI_StrChr(jvmtype, '\\')) { - sprintf(jvmpath, "%s\\" JVM_DLL, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s\\" JVM_DLL, jvmtype); } else { - sprintf(jvmpath, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); + JLI_Snprintf(jvmpath, jvmpathsize, "%s\\bin\\%s\\" JVM_DLL, jrepath, jvmtype); } if (stat(jvmpath, &s) == 0) { return JNI_TRUE;
--- a/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Thu Jul 15 20:11:45 2010 -0700 +++ b/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Tue Jul 20 22:21:31 2010 -0700 @@ -312,14 +312,17 @@ private int processSelectedKeys(long updateCount) { int numKeysUpdated = 0; numKeysUpdated += processFDSet(updateCount, readFds, - PollArrayWrapper.POLLIN); + PollArrayWrapper.POLLIN, + false); numKeysUpdated += processFDSet(updateCount, writeFds, PollArrayWrapper.POLLCONN | - PollArrayWrapper.POLLOUT); + PollArrayWrapper.POLLOUT, + false); numKeysUpdated += processFDSet(updateCount, exceptFds, PollArrayWrapper.POLLIN | PollArrayWrapper.POLLCONN | - PollArrayWrapper.POLLOUT); + PollArrayWrapper.POLLOUT, + true); return numKeysUpdated; } @@ -331,7 +334,9 @@ * * me.updateCount <= me.clearedCount <= updateCount */ - private int processFDSet(long updateCount, int[] fds, int rOps) { + private int processFDSet(long updateCount, int[] fds, int rOps, + boolean isExceptFds) + { int numKeysUpdated = 0; for (int i = 1; i <= fds[0]; i++) { int desc = fds[i]; @@ -347,6 +352,17 @@ if (me == null) continue; SelectionKeyImpl sk = me.ski; + + // The descriptor may be in the exceptfds set because there is + // OOB data queued to the socket. If there is OOB data then it + // is discarded and the key is not added to the selected set. + if (isExceptFds && + (sk.channel() instanceof SocketChannelImpl) && + discardUrgentData(desc)) + { + continue; + } + if (selectedKeys.contains(sk)) { // Key in selected set if (me.clearedCount != updateCount) { if (sk.channel.translateAndSetReadyOps(rOps, sk) && @@ -460,6 +476,8 @@ private native void resetWakeupSocket0(int wakeupSourceFd); + private native boolean discardUrgentData(int fd); + // We increment this counter on each call to updateSelectedKeys() // each entry in SubSelector.fdsMap has a memorized value of // updateCount. When we increment numKeysUpdated we set updateCount
--- a/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/windows/native/sun/java2d/opengl/WGLSurfaceData.c Tue Jul 20 22:21:31 2010 -0700 @@ -66,6 +66,10 @@ J2dTraceLn(J2D_TRACE_INFO, "WGLSurfaceData_initOps"); + if (oglsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } if (wglsdo == NULL) { JNU_ThrowOutOfMemoryError(env, "creating native wgl ops"); return;
--- a/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Thu Jul 15 20:11:45 2010 -0700 +++ b/src/windows/native/sun/java2d/windows/GDIWindowSurfaceData.cpp Tue Jul 20 22:21:31 2010 -0700 @@ -363,6 +363,10 @@ { J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initOps"); GDIWinSDOps *wsdo = (GDIWinSDOps *)SurfaceData_InitOps(env, wsd, sizeof(GDIWinSDOps)); + if (wsdo == NULL) { + JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); + return; + } wsdo->sdOps.Lock = GDIWinSD_Lock; wsdo->sdOps.GetRasInfo = GDIWinSD_GetRasInfo; wsdo->sdOps.Unlock = GDIWinSD_Unlock;
--- a/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Thu Jul 15 20:11:45 2010 -0700 +++ b/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Tue Jul 20 22:21:31 2010 -0700 @@ -214,3 +214,19 @@ recv(scinFd, bytes, WAKEUP_SOCKET_BUF_SIZE, 0); } } + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_WindowsSelectorImpl_discardUrgentData(JNIEnv* env, jobject this, + jint s) +{ + char data[8]; + jboolean discarded = JNI_FALSE; + int n; + do { + n = recv(s, &data, sizeof(data), MSG_OOB); + if (n > 0) { + discarded = JNI_TRUE; + } + } while (n > 0); + return discarded; +}
--- a/test/Makefile Thu Jul 15 20:11:45 2010 -0700 +++ b/test/Makefile Tue Jul 20 22:21:31 2010 -0700 @@ -495,19 +495,17 @@ jdk_nio1: java/nio/file $(call RunSamevmBatch) -# Stable othervm testruns (minus items from PROBLEM_LIST) -# Using samevm has serious problems with these tests +# Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_nio2 jdk_nio2: java/nio/Buffer java/nio/ByteOrder \ java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer $(call SharedLibraryPermissions,java/nio/channels) - $(call RunOthervmBatch) + $(call RunSamevmBatch) -# Stable othervm testruns (minus items from PROBLEM_LIST) -# Using samevm has serious problems with these tests +# Stable samevm testruns (minus items from PROBLEM_LIST) JDK_ALL_TARGETS += jdk_nio3 jdk_nio3: com/sun/nio sun/nio - $(call RunOthervmBatch) + $(call RunSamevmBatch) # All nio tests jdk_nio: jdk_nio1 jdk_nio2 jdk_nio3
--- a/test/ProblemList.txt Thu Jul 15 20:11:45 2010 -0700 +++ b/test/ProblemList.txt Tue Jul 20 22:21:31 2010 -0700 @@ -295,9 +295,6 @@ # jdk_misc -# On Windows com.sun.java.swing.plaf.gtk does not exist, always fails there -com/sun/java/swing/plaf/gtk/Test6635110.java windows-all - # Need to be marked othervm, or changed to be samevm safe com/sun/jndi/ldap/ReadTimeoutTest.java generic-all com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java generic-all @@ -379,9 +376,6 @@ # Interrupted or IO exception, maybe writing to non-unique named file? com/sun/net/httpserver/bugs/B6373555.java generic-all -# Fails on OpenSolaris, BindException unexpected -java/net/BindException/Test.java generic-all - # Fails on OpenSolaris, times out java/net/MulticastSocket/SetOutgoingIf.java generic-all @@ -507,25 +501,46 @@ ############################################################################ +# jdk_io + +# 6962637 +java/io/File/MaxPathLength.java windows-all + +############################################################################ + # jdk_nio -# Suspect many of these tests auffer from using fixed ports, no concrete -# evidence. +# 6944810 +java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all + +# 6963118 +java/nio/channels/Selector/Wakeup.java windows-all -# Occasionally Failing with java.lang.AssertionError on Windows X64 -# at sun.nio.ch.PendingIoCache.clearPendingIoMap(PendingIoCache.java:144) -#java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java windows-all +# The asynchronous I/O implementation on Windows requires Windows XP or newer. +# We can remove the following once all Windows 2000 machines have been +# decommissioned. +java/nio/channels/AsynchronousChannelGroup/Basic.java windows-5.0 +java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java windows-5.0 +java/nio/channels/AsynchronousChannelGroup/Identity.java windows-5.0 +java/nio/channels/AsynchronousChannelGroup/Restart.java windows-5.0 +java/nio/channels/AsynchronousChannelGroup/Unbounded.java windows-5.0 +java/nio/channels/AsynchronousDatagramChannel/Basic.java windows-5.0 +java/nio/channels/AsynchronousFileChannel/Lock.java windows-5.0 +java/nio/channels/AsynchronousServerSocketChannel/Basic.java windows-5.0 +java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0 +java/nio/channels/AsynchronousSocketChannel/Basic.java windows-5.0 +java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0 +java/nio/channels/AsynchronousSocketChannel/Leaky.java windows-5.0 +java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0 +java/nio/channels/Channels/Basic2.java windows-5.0 -# Some kind of sleep/wake problem on Windows X64 -java/nio/channels/Selector/Wakeup.java windows-all +# 6959891 +com/sun/nio/sctp/SctpChannel/SocketOptionTests.java # Fails with -ea -esa, Assertion error, but only on Solaris 10 machines? com/sun/nio/sctp/SctpChannel/Send.java generic-all com/sun/nio/sctp/SctpChannel/Shutdown.java generic-all -# Fails on Windows 2000, times out -java/nio/channels/FileChannel/Transfer.java generic-all - # Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses # from a channel that is bound to the wildcard address com/sun/nio/sctp/SctpChannel/Bind.java generic-all @@ -533,18 +548,6 @@ # Failed on OpenSolaris, java.lang.AssertionError: Unknown event type com/sun/nio/sctp/SctpChannel/Receive.java generic-all -# Triggers a hotspot crash on Fedora 9 32bit -server and Windows X64 samevm -sun/nio/cs/TestUTF8.java generic-all - -# Runtime exception on windows X64, samevm mode -java/nio/channels/Selector/WakeupNow.java generic-all - -# Occasional errors, solarix x86, address already in use, othervm mode -java/nio/channels/Selector/SelectorTest.java generic-all - -# Fails on Linux Fedora 9 X64 -sun/nio/cs/FindDecoderBugs.java generic-all - # Solaris 11 gave assert error and "connection refused", samevm issues? com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java generic-all @@ -555,49 +558,6 @@ com/sun/nio/sctp/SctpMultiChannel/Send.java generic-all com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java generic-all -# Linux 64bit failures. too many files open -java/nio/channels/Selector/HelperSlowToDie.java generic-all - -# Gets java.lang.ExceptionInInitializerError on Windows 2000 (need XP or newer) -java/nio/channels/AsynchronousChannelGroup/Basic.java windows-5.0 -java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java windows-5.0 -java/nio/channels/AsynchronousChannelGroup/Identity.java windows-5.0 -java/nio/channels/AsynchronousChannelGroup/Restart.java windows-5.0 -java/nio/channels/AsynchronousChannelGroup/Unbounded.java windows-5.0 -java/nio/channels/AsynchronousDatagramChannel/Basic.java windows-5.0 -java/nio/channels/AsynchronousFileChannel/Lock.java windows-5.0 -java/nio/channels/AsynchronousServerSocketChannel/Basic.java windows-5.0 -java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0 -java/nio/channels/AsynchronousSocketChannel/Basic.java windows-5.0 -java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0 -java/nio/channels/AsynchronousSocketChannel/Leaky.java windows-5.0 -java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0 -java/nio/channels/Channels/Basic2.java windows-5.0 - -# Failed loopback connection? On windows 32bit? -# Considered a stress test, can consume all resources. -java/nio/channels/Selector/LotsOfChannels.java generic-all - -# Windows i586 client, crashed hotspot? Unpredictable -# Considered a stress test, can consume all resources. -java/nio/channels/Selector/RegAfterPreClose.java generic-all - -# Solaris i586, cannot assign address, samevm issues -java/nio/channels/Selector/SelectorLimit.java generic-all - -# Socket timeout windows X64 -java/nio/channels/ServerSocketChannel/AdaptServerSocket.java windows-all - -# Timeouts etc. on Window -java/nio/channels/SocketChannel/ConnectState.java windows-all -java/nio/channels/SocketChannel/FinishConnect.java windows-all - -# Fails on all platforms due to overlap of JDK jar file contents: -sun/nio/cs/Test4200310.sh generic-all - -# Depends on motif packages that do not exist all the time: -sun/nio/cs/TestX11CNS.java generic-all - ############################################################################ # jdk_rmi @@ -848,9 +808,6 @@ # jdk_swing (not using samevm) -# Fails on solaris 10 sparc, throws RuntimeException that just says "failed" -javax/swing/JLabel/6501991/bug6501991.java generic-all - # Fails on solaris 11 i586, with othervm javax/swing/JFileChooser/6570445/bug6570445.java generic-all javax/swing/JFileChooser/6738668/bug6738668.java generic-all
--- a/test/com/sun/java/swing/plaf/gtk/Test6635110.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/com/sun/java/swing/plaf/gtk/Test6635110.java Tue Jul 20 22:21:31 2010 -0700 @@ -28,7 +28,6 @@ @run main Test6635110 */ -import com.sun.java.swing.plaf.gtk.GTKLookAndFeel; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; @@ -59,7 +58,12 @@ } public static void main(String[] args) throws Exception { - UIManager.setLookAndFeel(new GTKLookAndFeel()); + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception e) { + System.out.println("GTKLookAndFeel cannot be set, skipping this test"); + return; + } SwingUtilities.invokeAndWait(new Test6635110()); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/com/sun/java/swing/plaf/gtk/Test6963870.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6963870 + @summary Tests that GTKPainter.ListTableFocusBorder.getBorderInsets() + doesn't return null + @author Peter Zhelezniakov + @run main Test6963870 +*/ + +import java.awt.Insets; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.border.Border; + +public class Test6963870 implements Runnable { + + final static String[] UI_NAMES = { + "List.focusCellHighlightBorder", + "List.focusSelectedCellHighlightBorder", + "List.noFocusBorder", + "Table.focusCellHighlightBorder", + "Table.focusSelectedCellHighlightBorder", + }; + + public void run() { + for (String uiName: UI_NAMES) { + test(uiName); + } + } + + void test(String uiName) { + Border b = UIManager.getBorder(uiName); + Insets i = b.getBorderInsets(null); + if (i == null) { + throw new RuntimeException("getBorderInsets() returns null for " + uiName); + } + } + + public static void main(String[] args) throws Exception { + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (Exception e) { + System.out.println("GTKLookAndFeel cannot be set, skipping this test"); + return; + } + + SwingUtilities.invokeAndWait(new Test6963870()); + } +} +
--- a/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,3 +1,26 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + /* @test @bug 6304473 6727884
--- a/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java Tue Jul 20 22:21:31 2010 -0700 @@ -34,35 +34,40 @@ import java.awt.*; import java.awt.event.*; -import java.lang.Math; + +import sun.awt.SunToolkit; + import test.java.awt.regtesthelpers.Util; public class LoopRobustness { - static int clicks = 0; + final static long TIMEOUT = 5000; final static Object LOCK = new Object(); - static volatile boolean notifyOccur = false; - public static void main(String [] args) { + public static int clicks = 0; + public static volatile boolean notifyOccured = false; + public static volatile boolean otherExceptionsCaught = false; + + public static void main(String [] args) throws Exception { ThreadGroup mainThreadGroup = Thread.currentThread().getThreadGroup(); long at; //wait for a TIMEOUT giving a chance to a new Thread above to accomplish its stuff. - synchronized (LoopRobustness.LOCK){ + synchronized (LoopRobustness.LOCK) { new Thread(new TestThreadGroup(mainThreadGroup, "TestGroup"), new Impl()).start(); at = System.currentTimeMillis(); try { - while(!notifyOccur && System.currentTimeMillis() - at < TIMEOUT) { + while (!notifyOccured && (System.currentTimeMillis() - at < TIMEOUT)) { LoopRobustness.LOCK.wait(1000); } - } catch(InterruptedException e){ + } catch (InterruptedException e) { throw new RuntimeException("Test interrupted.", e); } } - if( !notifyOccur){ + if (!notifyOccured) { //notify doesn't occur after a reasonable time. - throw new RuntimeException("Test failed. Second Thread didn't notify MainThread."); + throw new RuntimeException("Test FAILED: second thread hasn't notified MainThread"); } //now wait for two clicks @@ -75,7 +80,10 @@ } } if (clicks != 2) { - throw new RuntimeException("robot should press button twice"); + throw new RuntimeException("Test FAILED: robot should press button twice"); + } + if (otherExceptionsCaught) { + throw new RuntimeException("Test FAILED: unexpected exceptions caught"); } } } @@ -83,18 +91,11 @@ class Impl implements Runnable{ static Robot robot; public void run() { + SunToolkit.createNewAppContext(); + Button b = new Button("Press me to test the AWT-Event Queue thread"); Frame lr = new Frame("ROBUST FRAME"); - /* Must load Toolkit on this thread only, rather then on Main. - If load on Main (on the parent ThreadGroup of current ThreadGroup) then - EDT will be created on Main thread and supplied with it's own exceptionHandler, - which just throws an Exception and terminates current thread. - The test implies that EDT is created on the child ThreadGroup (testThreadGroup) - which is supplied with its own uncaughtException(). - */ - Toolkit.getDefaultToolkit(); lr.setBounds(100, 100, 300, 100); - b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { LoopRobustness.clicks++; @@ -107,40 +108,46 @@ try { robot = new Robot(); - } catch(AWTException e){ + } catch (AWTException e) { throw new RuntimeException("Test interrupted.", e); } Util.waitForIdle(robot); synchronized (LoopRobustness.LOCK){ LoopRobustness.LOCK.notify(); - LoopRobustness.notifyOccur = true; + LoopRobustness.notifyOccured = true; } int i = 0; - while(i < 2){ + while (i < 2) { robot.mouseMove(b.getLocationOnScreen().x + b.getWidth()/2, - b.getLocationOnScreen().y + b.getHeight()/2 ); + b.getLocationOnScreen().y + b.getHeight()/2); + Util.waitForIdle(robot); robot.mousePress(InputEvent.BUTTON1_MASK); - // robot.delay(10); + Util.waitForIdle(robot); robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); i++; - robot.delay(1000); } } } class TestThreadGroup extends ThreadGroup { - TestThreadGroup(ThreadGroup threadGroup, String name){ + TestThreadGroup(ThreadGroup threadGroup, String name) { super(threadGroup, name); } - public void uncaughtException(Thread exitedThread, Throwable e) { - e.printStackTrace(); - if ((e instanceof ExceptionInInitializerError) || (e instanceof - NoClassDefFoundError)){ - throw new RuntimeException("Test failed: other Exceptions were thrown ", e); + public void uncaughtException(Thread thread, Throwable e) { + System.out.println("Exception caught: " + e); + e.printStackTrace(System.out); + System.out.flush(); + if ((e instanceof ExceptionInInitializerError) || + (e instanceof NoClassDefFoundError)) + { + // These two are expected + return; } + LoopRobustness.otherExceptionsCaught = true; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/EventDispatchThread/PreserveDispathThread/PreserveDispatchThread.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 6424157 + @author Artem Ananiev: area=eventqueue + @run main PreserveDispatchThread +*/ + +import java.awt.*; +import java.awt.event.*; + +public class PreserveDispatchThread { + + private static volatile Frame f; + private static volatile Dialog d; + + private static volatile boolean isEDT = true; + + public static void main(String[] args) throws Exception { + f = new Frame("F"); + f.setSize(320, 340); + f.setLocationRelativeTo(null); + f.setVisible(true); + + try { + test1(); + if (!isEDT) { + throw new RuntimeException("Test FAILED (test1): event dispatch thread is changed"); + } + + test2(); + if (!isEDT) { + throw new RuntimeException("Test FAILED (test2): event dispatch thread is changed"); + } + + test3(); + if (!isEDT) { + throw new RuntimeException("Test FAILED (test3): event dispatch thread is changed"); + } + } finally { + if (d != null) { + d.dispose(); + } + f.dispose(); + } + } + + /* + * Tests that push/pop doesn't change the dispatch thread if + * called on EDT. + */ + private static void test1() throws Exception { + EventQueue.invokeAndWait(new Runnable() { + @Override + public void run() { + TestEventQueue teq = new TestEventQueue(); + EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + try { + seq.push(teq); + d = new TestDialog(); + d.setVisible(true); + checkEDT(); + } finally { + teq.pop(); + } + checkEDT(); + } + }); + } + + /* + * Tests that push/pop doesn't change the dispatch thread if + * called on the main thread. + */ + private static void test2() throws Exception { + TestEventQueue teq = new TestEventQueue(); + EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + try { + seq.push(teq); + EventQueue.invokeAndWait(new Runnable() { + @Override + public void run() { + checkEDT(); + d = new TestDialog(); + d.setVisible(true); + checkEDT(); + } + }); + } finally { + teq.pop(); + } + } + + private static final Object test3Lock = new Object(); + private static boolean test3Sync = false; + + /* + * A complex test: several nested invokeLater() are called and + * in every runnable a check for EDT is performed. At the ent + * of the test we wait for all the runnables to be processed + * and the dialog is disposed; otherwise the last EDT check can + * be later than this method returns and the whole test is passed. + */ + private static void test3() throws Exception { + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + d = new Dialog(f, true); + d.setSize(240, 180); + d.setLocationRelativeTo(f); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + d.setVisible(true); + checkEDT(); + } + }); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + TestEventQueue teq = new TestEventQueue(); + EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue(); + try { + seq.push(teq); + checkEDT(); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + d.dispose(); + checkEDT(); + synchronized (test3Lock) { + test3Sync = true; + test3Lock.notify(); + } + } + }); + } finally { + teq.pop(); + } + checkEDT(); + } + }); + checkEDT(); + } + }); + synchronized (test3Lock) { + while (!test3Sync) { + try { + test3Lock.wait(); + } catch (InterruptedException ie) { + break; + } + } + } + // Make sure all the nested invokeLater/invokeAndWait are processed + EventQueue.invokeAndWait(new Runnable() { + @Override + public void run() { + } + }); + } + + private static void checkEDT() { + isEDT = isEDT && EventQueue.isDispatchThread(); + } + + private static class TestEventQueue extends EventQueue { + public TestEventQueue() { + super(); + } + public void pop() { + super.pop(); + } + } + + private static class TestDialog extends Dialog { + private volatile boolean dialogShown = false; + private volatile boolean paintCalled = false; + public TestDialog() { + super(f, true); + setSize(240, 180); + setLocationRelativeTo(f); + addComponentListener(new ComponentAdapter() { + @Override + public void componentShown(ComponentEvent e) { + if (paintCalled) { + dispose(); + } + dialogShown = true; + } + }); + } + @Override + public void paint(Graphics g) { + if (dialogShown) { + dispose(); + } + paintCalled = true; + } + } + +}
--- a/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/awt/EventQueue/PushPopDeadlock2/PushPopTest.java Tue Jul 20 22:21:31 2010 -0700 @@ -43,6 +43,7 @@ Runnable dummy = new Runnable() { public void run() { System.err.println("Dummy is here."); + System.err.flush(); } }; EventQueue seq = Toolkit.getDefaultToolkit().getSystemEventQueue(); @@ -58,10 +59,11 @@ Runnable runnable = new Runnable() { public void run() { System.err.println("Dummy from SunToolkit"); + System.err.flush(); } }; InvocationEvent ie = new InvocationEvent(eq2, runnable, null, false); - System.err.println(ie); +// System.err.println(ie); SunToolkit.postEvent(SunToolkit.targetToAppContext(frame), ie); eq1.pop(); frame.dispose(); @@ -70,14 +72,14 @@ class MyEventQueue1 extends EventQueue { - public void pop() throws EmptyStackException { + public void pop() { super.pop(); } } class MyEventQueue2 extends EventQueue { - protected void pop() throws EmptyStackException { + protected void pop() { System.err.println("pop2()"); Thread.dumpStack(); try { @@ -85,7 +87,8 @@ public void run() { Runnable runnable = new Runnable() { public void run() { - System.err.println("Dummy from here"); + System.err.println("Dummy from pop"); + System.err.flush(); } }; InvocationEvent ie = new InvocationEvent(MyEventQueue2.this, runnable, null, false);
--- a/test/java/awt/FontClass/FontPrivilege.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/awt/FontClass/FontPrivilege.java Tue Jul 20 22:21:31 2010 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 5010310 6319835 6904882 + * @bug 5010310 6319835 6904882 6968373 * @summary test fonts can be created in the presence of a security manager * @run main/othervm/secure=java.lang.SecurityManager FontPrivilege */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/beans/Introspector/Test6707234.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6707234 + * @summary Tests setter in a complex bean + * @author Sergey Malenkov + */ + +public class Test6707234 { + public static void main(String[] args) { + if (null == BeanUtils.getPropertyDescriptor(C.class, "number").getWriteMethod()) { + throw new Error("no write method"); + } + } + + public interface I { + void setNumber(Object number); + Number getNumber(); + } + + public class C implements I { + public void setNumber(Object value) { + } + public void setNumber(Long value) { + } + public Long getNumber() { + return null; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/beans/Introspector/Test6963811.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6963811 + * @summary Tests deadlock in Introspector + * @author Sergey Malenkov + */ + +import java.beans.Introspector; +import java.beans.SimpleBeanInfo; + +public class Test6963811 implements Runnable { + private final long time; + private final boolean sync; + + public Test6963811(long time, boolean sync) { + this.time = time; + this.sync = sync; + } + + public void run() { + try { + Thread.sleep(this.time); // increase the chance of the deadlock + Introspector.getBeanInfo( + this.sync ? Super.class : Sub.class, + this.sync ? null : Object.class); + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + Thread[] threads = new Thread[2]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(new Test6963811(0L, i > 0)); + threads[i].start(); + Thread.sleep(500L); // increase the chance of the deadlock + } + for (Thread thread : threads) { + thread.join(); + } + } + + public static class Super { + } + + public static class Sub extends Super { + } + + public static class SubBeanInfo extends SimpleBeanInfo { + public SubBeanInfo() { + new Test6963811(1000L, true).run(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/beans/PropertyEditor/Test6963811.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6963811 + * @summary Tests deadlock in PropertyEditorManager + * @author Sergey Malenkov + */ + +import java.beans.PropertyEditorManager; +import sun.beans.editors.StringEditor; + +public class Test6963811 implements Runnable { + private final long time; + private final boolean sync; + + public Test6963811(long time, boolean sync) { + this.time = time; + this.sync = sync; + } + + public void run() { + try { + Thread.sleep(this.time); // increase the chance of the deadlock + if (this.sync) { + synchronized (Test6963811.class) { + PropertyEditorManager.findEditor(Super.class); + } + } + else { + PropertyEditorManager.findEditor(Sub.class); + } + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + Thread[] threads = new Thread[2]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(new Test6963811(0L, i > 0)); + threads[i].start(); + Thread.sleep(500L); // increase the chance of the deadlock + } + for (Thread thread : threads) { + thread.join(); + } + } + + public static class Super { + } + + public static class Sub extends Super { + } + + public static class SubEditor extends StringEditor { + public SubEditor() { + new Test6963811(1000L, true).run(); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/beans/XMLEncoder/Test6963811.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6963811 + * @summary Tests deadlock in Encoder + * @author Sergey Malenkov + */ + +import java.beans.Encoder; +import java.beans.DefaultPersistenceDelegate; + +public class Test6963811 implements Runnable { + private static final Encoder ENCODER = new Encoder(); + private final long time; + private final boolean sync; + + public Test6963811(long time, boolean sync) { + this.time = time; + this.sync = sync; + } + + public void run() { + try { + Thread.sleep(this.time); // increase the chance of the deadlock + if (this.sync) { + synchronized (Test6963811.class) { + ENCODER.getPersistenceDelegate(Super.class); + } + } + else { + ENCODER.getPersistenceDelegate(Sub.class); + } + } + catch (Exception exception) { + exception.printStackTrace(); + } + } + + public static void main(String[] args) throws Exception { + Thread[] threads = new Thread[2]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new Thread(new Test6963811(0L, i > 0)); + threads[i].start(); + Thread.sleep(500L); // increase the chance of the deadlock + } + for (Thread thread : threads) { + thread.join(); + } + } + + public static class Super { + } + + public static class Sub extends Super { + } + + public static class SubPersistenceDelegate extends DefaultPersistenceDelegate { + public SubPersistenceDelegate() { + new Test6963811(1000L, true).run(); + } + } +}
--- a/test/java/lang/String/Supplementary.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/lang/String/Supplementary.java Tue Jul 20 22:21:31 2010 -0700 @@ -62,7 +62,7 @@ 0 1 2345 678 9 012 345678 9 01 2 */ "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00", - // includes an undefined supprementary characters in Unicode 4.0.0 + // includes an undefined supplementary character in Unicode 4.0.0 /* 1 11 1 1111 1 0 1 2345 6 789 0 12 3 4567 8 */ "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02", @@ -168,7 +168,7 @@ * string in input[m]. * * The meaning of each element in golden3[][n] - * golden3[][0]: characater which is searched. + * golden3[][0]: character which is searched. * golden3[][2]: the golden data for indexOf(int ch) * From golden3[][2] to golden3[][n-1]: * the golden data for indexOf(int ch, int fromIndex) @@ -201,17 +201,17 @@ /* * Normal case */ - testIndexOf(First, s, golden3[i][0], golden3[i][2]); + testIndexOf(s, golden3[i][0], golden3[i][2]); /* * Abnormal case - char which isn't included in the string. */ - testIndexOf(First, s, 'Z', -1); - testIndexOf(First, s, 0xDB98, -1); - testIndexOf(First, s, 0xDE76, -1); - testIndexOf(First, s, 0x12345, -1); - testIndexOf(First, s, -1, -1); - testIndexOf(First, s, 0x110000, -1); + testIndexOf(s, 'Z', -1); + testIndexOf(s, 0xDB98, -1); + testIndexOf(s, 0xDE76, -1); + testIndexOf(s, 0x12345, -1); + testIndexOf(s, -1, -1); + testIndexOf(s, 0x110000, -1); } } @@ -229,7 +229,7 @@ */ int fromIndex = 0; for (int j = 2; j < golden3[i].length; j++) { - fromIndex = testIndexOf(First, s, fromIndex, ch, + fromIndex = testIndexOf(s, fromIndex, ch, golden3[i][j]) + 1; } @@ -237,19 +237,19 @@ * Abnormal case1 - char is included in the string but fromIndex * is incorrect. */ - testIndexOf(First, s, -1, ch, golden3[i][2]); - testIndexOf(First, s, s.length(), ch, + testIndexOf(s, -1, ch, golden3[i][2]); + testIndexOf(s, s.length(), ch, golden3[i][golden3[i].length-1]); /* * Abnormal case2 - char which isn't included in the string. */ - testIndexOf(First, s, 0, 'Z', -1); - testIndexOf(First, s, 0, 0xDB98, -1); - testIndexOf(First, s, 0, 0xDE76, -1); - testIndexOf(First, s, 0, 0x12345, -1); - testIndexOf(First, s, 0, -1, -1); - testIndexOf(First, s, 0, 0x110000, -1); + testIndexOf(s, 0, 'Z', -1); + testIndexOf(s, 0, 0xDB98, -1); + testIndexOf(s, 0, 0xDE76, -1); + testIndexOf(s, 0, 0x12345, -1); + testIndexOf(s, 0, -1, -1); + testIndexOf(s, 0, 0x110000, -1); } } @@ -264,18 +264,18 @@ /* * Normal case */ - testIndexOf(Last, s, golden3[i][0], + testLastIndexOf(s, golden3[i][0], golden3[i][golden3[i].length-2]); /* * Abnormal case - char which isn't included in the string. */ - testIndexOf(Last, s, 'Z', -1); - testIndexOf(Last, s, 0xDB98, -1); - testIndexOf(Last, s, 0xDE76, -1); - testIndexOf(Last, s, 0x12345, -1); - testIndexOf(Last, s, -1, -1); - testIndexOf(Last, s, 0x110000, -1); + testLastIndexOf(s, 'Z', -1); + testLastIndexOf(s, 0xDB98, -1); + testLastIndexOf(s, 0xDE76, -1); + testLastIndexOf(s, 0x12345, -1); + testLastIndexOf(s, -1, -1); + testLastIndexOf(s, 0x110000, -1); } } @@ -294,7 +294,7 @@ */ int fromIndex = len - 1; for (int j = golden3[i].length - 2; j > 0; j--) { - fromIndex = testIndexOf(Last, s, fromIndex, ch, + fromIndex = testLastIndexOf(s, fromIndex, ch, golden3[i][j]) - 1; } @@ -302,18 +302,18 @@ * Abnormal case1 - char is included in the string but fromIndex * is incorrect. */ - testIndexOf(Last, s, -1, ch, golden3[i][1]); - testIndexOf(Last, s, len, ch, golden3[i][golden3[i].length-2]); + testLastIndexOf(s, -1, ch, golden3[i][1]); + testLastIndexOf(s, len, ch, golden3[i][golden3[i].length-2]); /* * Abnormal case2 - char which isn't included in the string. */ - testIndexOf(Last, s, len, 'Z', -1); - testIndexOf(Last, s, len, 0xDB98, -1); - testIndexOf(Last, s, len, 0xDE76, -1); - testIndexOf(Last, s, len, 0x12345, -1); - testIndexOf(Last, s, len, -1, -1); - testIndexOf(Last, s, len, 0x110000, -1); + testLastIndexOf(s, len, 'Z', -1); + testLastIndexOf(s, len, 0xDB98, -1); + testLastIndexOf(s, len, 0xDE76, -1); + testLastIndexOf(s, len, 0x12345, -1); + testLastIndexOf(s, len, -1, -1); + testLastIndexOf(s, len, 0x110000, -1); } } @@ -471,7 +471,7 @@ result, expected); result = str.offsetByCodePoints(j, -nCodePoints); check(result != 0, - "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")", + "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")", result, 0); } @@ -531,7 +531,7 @@ result, expected); result = str.offsetByCodePoints(j, -nCodePoints); check(result != 0, - "offsetBycodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")", + "offsetByCodePoints(input["+i+"], "+j+", "+(-nCodePoints)+")", result, 0); } } @@ -539,7 +539,7 @@ static final boolean At = true, Before = false; - static final boolean First = true, Last = false; + static final boolean FIRST = true, LAST = false; static void testCodePoint(boolean isAt, String s, int index, int expected) { int c = isAt ? s.codePointAt(index) : s.codePointBefore(index); @@ -563,22 +563,72 @@ + s + "> should throw StringIndexOutOfBoundsPointerException."); } - static void testIndexOf(boolean isFirst, String s, int c, int expected) { - int index = isFirst ? s.indexOf(c) : s.lastIndexOf(c); + static void testIndexOf(String s, int c, int expected) { + testIndexOf2(s, c, expected); + if (s.indexOf(c) != -1) { + testIndexOf2(s + (char) c, c, expected); + if (Character.isSupplementaryCodePoint(c)) { + char[] surrogates = Character.toChars(c); + testIndexOf2(s + new String(surrogates), c, expected); + testIndexOf2(s + surrogates[0], c, expected); + testIndexOf2(s + surrogates[1], c, expected); + testIndexOf2(new String(surrogates) + s, c, 0); + testIndexOf2(surrogates[0] + s, c, expected + 1); + testIndexOf2(surrogates[1] + s, c, expected + 1); + } + } + } + + static void testIndexOf2(String s, int c, int expected) { + int index = s.indexOf(c); check(index != expected, - (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c) - + ") for <" + s + ">", index, expected); + "indexOf(" + toHexString(c) + ") for <" + s + ">", + index, expected); } - static int testIndexOf(boolean isFirst, String s, int fromIndex, int c, - int expected) { - int index = isFirst ? s.indexOf(c, fromIndex) : - s.lastIndexOf(c, fromIndex); + static void testLastIndexOf(String s, int c, int expected) { + testLastIndexOf2(s, c, expected); + if (s.lastIndexOf(c) != -1) { + testLastIndexOf2((char) c + s, c, expected + 1); + if (Character.isSupplementaryCodePoint(c)) { + char[] surrogates = Character.toChars(c); + testLastIndexOf2(s + new String(surrogates), c, s.length()); + testLastIndexOf2(s + surrogates[0], c, expected); + testLastIndexOf2(s + surrogates[1], c, expected); + testLastIndexOf2(new String(surrogates) + s, c, expected + 2); + testLastIndexOf2(surrogates[0] + s, c, expected + 1); + testLastIndexOf2(surrogates[1] + s, c, expected + 1); + } + } + } + + static void testLastIndexOf2(String s, int c, int expected) { + int index = s.lastIndexOf(c); check(index != expected, - (isFirst ? "i" : "lastI") + "ndexOf(" + toHexString(c) + ", " - + fromIndex + ") for <" + s + ">", index, expected); + "lastIndexOf(" + toHexString(c) + ") for <" + s + ">", + index, expected); + } + + static int testIndexOf(String s, int fromIndex, int c, int expected) { + int index = s.indexOf(c, fromIndex); + + check(index != expected, + "indexOf(" + toHexString(c) + ", " + + fromIndex + ") for <" + s + ">", + index, expected); + + return index; + } + + static int testLastIndexOf(String s, int fromIndex, int c, int expected) { + int index = s.lastIndexOf(c, fromIndex); + + check(index != expected, + "lastIndexOf(" + toHexString(c) + ", " + + fromIndex + ") for <" + s + ">", + index, expected); return index; }
--- a/test/java/lang/StringBuffer/Supplementary.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/lang/StringBuffer/Supplementary.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,7 +24,7 @@ /* * * @test - * @bug 4533872 4915683 4985217 5017280 + * @bug 4533872 4915683 4985217 5017280 6937112 * @summary Unit tests for supplementary character support (JSR-204) */ @@ -57,7 +57,7 @@ 0 1 2345 678 9 012 345678 9 01 2 */ "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00", - // includes an undefined supprementary characters in Unicode 4.0.0 + // includes an undefined supplementary character in Unicode 4.0.0 /* 1 11 1 1111 1 0 1 2345 6 789 0 12 3 4567 8 */ "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02", @@ -151,7 +151,7 @@ "\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00", "\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00", - // includes an undefined supprementary characters in Unicode 4.0.0 + // includes an undefined supplementary character in Unicode 4.0.0 "\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00", };
--- a/test/java/lang/StringBuilder/Supplementary.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/lang/StringBuilder/Supplementary.java Tue Jul 20 22:21:31 2010 -0700 @@ -57,7 +57,7 @@ 0 1 2345 678 9 012 345678 9 01 2 */ "\uD800\uDC00!#$\uD800%&\uD800\uDC00;+\uDC00<>;=^\uDC00\\@\uD800\uDC00", - // includes an undefined supprementary characters in Unicode 4.0.0 + // includes an undefined supplementary character in Unicode 4.0.0 /* 1 11 1 1111 1 0 1 2345 6 789 0 12 3 4567 8 */ "\uDB40\uDE00abc\uDE01\uDB40de\uDB40\uDE02f\uDB40\uDE03ghi\uDB40\uDE02", @@ -151,7 +151,7 @@ "\uD800on\uDC00ml\uDC00\uDC00ki9\uD800\uDC00hgfe\uDBFF\uDFFFdcba\uDC00", "\uD800\uDC00@\\\uDC00^=;><\uDC00+;\uD800\uDC00&%\uD800$#!\uD800\uDC00", - // includes an undefined supprementary characters in Unicode 4.0.0 + // includes an undefined supplementary character in Unicode 4.0.0 "\uDB40\uDE02ihg\uDB40\uDE03f\uDB40\uDE02ed\uDB40\uDE01cba\uDB40\uDE00", };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/lang/Throwable/SuppressedExceptions.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.util.*; + +/* + * @test + * @bug 6911258 6962571 + * @summary Basic tests of suppressed exceptions + * @author Joseph D. Darcy + */ + +public class SuppressedExceptions { + private static String message = "Bad suppressed exception information"; + + public static void main(String... args) throws Exception { + basicSupressionTest(); + serializationTest(); + selfReference(); + } + + private static void basicSupressionTest() { + Throwable throwable = new Throwable(); + RuntimeException suppressed = new RuntimeException("A suppressed exception."); + AssertionError repressed = new AssertionError("A repressed error."); + + Throwable[] t0 = throwable.getSuppressedExceptions(); + if (t0.length != 0) { + throw new RuntimeException(message); + } + throwable.printStackTrace(); + + throwable.addSuppressedException(suppressed); + Throwable[] t1 = throwable.getSuppressedExceptions(); + if (t1.length != 1 || + t1[0] != suppressed) {throw new RuntimeException(message); + } + throwable.printStackTrace(); + + throwable.addSuppressedException(repressed); + Throwable[] t2 = throwable.getSuppressedExceptions(); + if (t2.length != 2 || + t2[0] != suppressed || + t2[1] != repressed) { + throw new RuntimeException(message); + } + throwable.printStackTrace(); + } + + private static void serializationTest() throws Exception { + /* + * Bytes of the serial form of + * + * (new Throwable())setStackTrace(new StackTraceElement[0]) + * + * from JDK 6; suppressedException field will be missing and + * thus default to null upon deserialization. + */ + byte[] bytes = { + (byte)0xac, (byte)0xed, (byte)0x00, (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13, + (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, + (byte)0x67, (byte)0x2e, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, + (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39, + (byte)0x77, (byte)0xb8, (byte)0xcb, (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00, + (byte)0x05, (byte)0x63, (byte)0x61, (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00, + (byte)0x15, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, + (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, + (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00, + (byte)0x0d, (byte)0x64, (byte)0x65, (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d, + (byte)0x65, (byte)0x73, (byte)0x73, (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00, + (byte)0x12, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, + (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69, + (byte)0x6e, (byte)0x67, (byte)0x3b, (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74, + (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, + (byte)0x74, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, + (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, + (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, + (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, + (byte)0x3b, (byte)0x78, (byte)0x70, (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04, + (byte)0x70, (byte)0x75, (byte)0x72, (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, + (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, + (byte)0x2e, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, + (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, + (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c, + (byte)0xfd, (byte)0x22, (byte)0x39, (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, + (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0xac, (byte)0xed, (byte)0x00, + (byte)0x05, (byte)0x73, (byte)0x72, (byte)0x00, (byte)0x13, (byte)0x6a, (byte)0x61, (byte)0x76, + (byte)0x61, (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x54, + (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, + (byte)0xd5, (byte)0xc6, (byte)0x35, (byte)0x27, (byte)0x39, (byte)0x77, (byte)0xb8, (byte)0xcb, + (byte)0x03, (byte)0x00, (byte)0x03, (byte)0x4c, (byte)0x00, (byte)0x05, (byte)0x63, (byte)0x61, + (byte)0x75, (byte)0x73, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x15, (byte)0x4c, (byte)0x6a, + (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, + (byte)0x2f, (byte)0x54, (byte)0x68, (byte)0x72, (byte)0x6f, (byte)0x77, (byte)0x61, (byte)0x62, + (byte)0x6c, (byte)0x65, (byte)0x3b, (byte)0x4c, (byte)0x00, (byte)0x0d, (byte)0x64, (byte)0x65, + (byte)0x74, (byte)0x61, (byte)0x69, (byte)0x6c, (byte)0x4d, (byte)0x65, (byte)0x73, (byte)0x73, + (byte)0x61, (byte)0x67, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x12, (byte)0x4c, (byte)0x6a, + (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x6e, (byte)0x67, (byte)0x3b, + (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69, + (byte)0x5b, (byte)0x00, (byte)0x0a, (byte)0x73, (byte)0x74, (byte)0x61, (byte)0x63, (byte)0x6b, + (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x74, (byte)0x00, (byte)0x1e, + (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, + (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x61, (byte)0x63, + (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, (byte)0x45, (byte)0x6c, + (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b, (byte)0x78, (byte)0x70, + (byte)0x71, (byte)0x00, (byte)0x7e, (byte)0x00, (byte)0x04, (byte)0x70, (byte)0x75, (byte)0x72, + (byte)0x00, (byte)0x1e, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, + (byte)0x2e, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2e, (byte)0x53, (byte)0x74, + (byte)0x61, (byte)0x63, (byte)0x6b, (byte)0x54, (byte)0x72, (byte)0x61, (byte)0x63, (byte)0x65, + (byte)0x45, (byte)0x6c, (byte)0x65, (byte)0x6d, (byte)0x65, (byte)0x6e, (byte)0x74, (byte)0x3b, + (byte)0x02, (byte)0x46, (byte)0x2a, (byte)0x3c, (byte)0x3c, (byte)0xfd, (byte)0x22, (byte)0x39, + (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x78, (byte)0x70, + }; + + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ObjectInputStream ois = new ObjectInputStream(bais); + + Object o = ois.readObject(); + Throwable throwable = (Throwable) o; + + System.err.println("TESTING SERIALIZED EXCEPTION"); + + Throwable[] t0 = throwable.getSuppressedExceptions(); + if (t0.length != 0) { // Will fail if t0 is null. + throw new RuntimeException(message); + } + throwable.printStackTrace(); + } + + private static void selfReference() { + Throwable throwable1 = new RuntimeException(); + Throwable throwable2 = new AssertionError(); + throwable1.initCause(throwable2); + throwable2.initCause(throwable1); + + throwable1.printStackTrace(); + + + throwable1.addSuppressedException(throwable1); + throwable1.addSuppressedException(throwable2); + + throwable1.printStackTrace(); + } +}
--- a/test/java/net/Authenticator/B4769350.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/net/Authenticator/B4769350.java Tue Jul 20 22:21:31 2010 -0700 @@ -54,6 +54,7 @@ boolean allowerror; Client (String authority, String path, boolean allowerror) { + super("Thread-" + path); this.authority = authority; this.path = path; this.allowerror = allowerror; @@ -72,7 +73,8 @@ error = true; } catch (IOException e) { if (!allowerror) { - System.out.println (e); + System.out.println (Thread.currentThread().getName() + " " + e); + e.printStackTrace(); error = true; } } @@ -94,6 +96,7 @@ } void okReply (HttpTransaction req) throws IOException { + req.addResponseHeader ("Connection", "close"); req.setResponseEntityBody ("Hello ."); req.sendResponse (200, "Ok"); req.orderlyClose();
--- a/test/java/net/BindException/Test.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/net/BindException/Test.java Tue Jul 20 22:21:31 2010 -0700 @@ -180,7 +180,7 @@ while (addrs.hasMoreElements()) { InetAddress ia = (InetAddress)addrs.nextElement(); - if (ia.isLoopbackAddress()) { + if (ia.isLoopbackAddress() || ia.isAnyLocalAddress()) { continue; }
--- a/test/java/net/Inet6Address/B6214234.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/net/Inet6Address/B6214234.java Tue Jul 20 22:21:31 2010 -0700 @@ -23,7 +23,7 @@ /** * @test - * @bug 6214234 + * @bug 6214234 6967937 * @summary IPv6 scope_id for local addresses not set in Solaris 10 */ @@ -51,6 +51,7 @@ return; } if (addr.getScopeId() == 0) { + System.out.println("addr: "+ addr); throw new RuntimeException ("Non zero scope_id expected"); } }
--- a/test/java/net/ipv6tests/Tests.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/net/ipv6tests/Tests.java Tue Jul 20 22:21:31 2010 -0700 @@ -248,7 +248,8 @@ } while (addrs.hasMoreElements()) { InetAddress addr = (InetAddress) addrs.nextElement(); - if (filter.isInstance (addr) && !addr.isLoopbackAddress()) { + if (filter.isInstance (addr) && !addr.isLoopbackAddress() + && !addr.isAnyLocalAddress()) { if (Arrays.equals (addr.getAddress(), fe80_loopback)) { continue; }
--- a/test/java/nio/BufferPoolMXBean/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/BufferPoolMXBean/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 6606598 * @summary Unit test for java.nio.BufferPoolMXBean + * @run main/othervm Basic */ import java.nio.ByteBuffer;
--- a/test/java/nio/MappedByteBuffer/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/MappedByteBuffer/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4462336 * @summary Simple MappedByteBuffer tests + * @run main/othervm Basic */ import java.io.*;
--- a/test/java/nio/MappedByteBuffer/Force.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/MappedByteBuffer/Force.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4625907 * @summary Testing force() + * @run main/othervm Force */ import java.io.*;
--- a/test/java/nio/MappedByteBuffer/ZeroMap.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/MappedByteBuffer/ZeroMap.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4802340 * @summary Testing force(), load() isLoaded() of zero len MBB + * @run main/othervm ZeroMap */ import java.io.*;
--- a/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Tue Jul 20 22:21:31 2010 -0700 @@ -29,6 +29,7 @@ import java.nio.ByteBuffer; import java.nio.channels.*; import java.net.*; +import java.util.*; import java.util.concurrent.*; import java.io.IOException; @@ -44,8 +45,12 @@ final AsynchronousServerSocketChannel listener = AsynchronousServerSocketChannel.open() .bind(new InetSocketAddress(0)); + final List<AsynchronousSocketChannel> accepted = new ArrayList<AsynchronousSocketChannel>(); listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() { public void completed(AsynchronousSocketChannel ch, Void att) { + synchronized (accepted) { + accepted.add(ch); + } listener.accept((Void)null, this); } public void failed(Throwable exc, Void att) { @@ -58,6 +63,14 @@ test(sa, true, false); test(sa, false, true); test(sa, true, true); + + // clean-up + listener.close(); + synchronized (accepted) { + for (AsynchronousSocketChannel ch: accepted) { + ch.close(); + } + } } static void test(SocketAddress sa,
--- a/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Tue Jul 20 22:21:31 2010 -0700 @@ -32,6 +32,7 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; +import java.io.IOException; /** * Tests that the completion handler is invoked by a thread with @@ -81,14 +82,18 @@ listener.accept((Void)null, new CompletionHandler<AsynchronousSocketChannel,Void>() { public void completed(final AsynchronousSocketChannel ch, Void att) { listener.accept((Void)null, this); - final ByteBuffer buf = ByteBuffer.allocate(100); - ch.read(buf, (Void)null, new CompletionHandler<Integer,Void>() { - public void completed(Integer bytesRead, Void att) { - buf.clear(); - ch.read(buf, (Void)null, this); + ch.read(buf, ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() { + public void completed(Integer bytesRead, AsynchronousSocketChannel ch) { + if (bytesRead < 0) { + try { ch.close(); } catch (IOException ignore) { } + } else { + buf.clear(); + ch.read(buf, ch, this); + } } - public void failed(Throwable exc, Void att) { + public void failed(Throwable exc, AsynchronousSocketChannel ch) { + try { ch.close(); } catch (IOException ignore) { } } }); } @@ -100,7 +105,8 @@ // create 3-10 channels, each in its own group final int groupCount = 3 + rand.nextInt(8); - final AsynchronousSocketChannel[] channel = new AsynchronousSocketChannel[groupCount]; + AsynchronousChannelGroup[] groups = new AsynchronousChannelGroup[groupCount]; + final AsynchronousSocketChannel[] channels = new AsynchronousSocketChannel[groupCount]; for (int i=0; i<groupCount; i++) { ThreadFactory factory = createThreadFactory(i); AsynchronousChannelGroup group; @@ -111,17 +117,18 @@ ExecutorService pool = Executors.newCachedThreadPool(factory); group = AsynchronousChannelGroup.withCachedThreadPool(pool, rand.nextInt(5)); } + groups[i] = group; // create channel in group and connect it to the server AsynchronousSocketChannel ch = AsynchronousSocketChannel.open(group); ch.connect(sa).get(); - channel[i] = ch; + channels[i] = ch; } // randomly write to each channel, ensuring that the completion handler // is always invoked by a thread with the right identity. final AtomicInteger writeCount = new AtomicInteger(100); - channel[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() { + channels[0].write(getBuffer(), 0, new CompletionHandler<Integer,Integer>() { public void completed(Integer bytesWritten, Integer groupId) { if (bytesWritten != 1) fail("Expected 1 byte to be written"); @@ -129,7 +136,7 @@ fail("Handler invoked by thread with the wrong identity"); if (writeCount.decrementAndGet() > 0) { int id = rand.nextInt(groupCount); - channel[id].write(getBuffer(), id, this); + channels[id].write(getBuffer(), id, this); } else { done.countDown(); } @@ -139,8 +146,16 @@ } }); - // wait until + // wait until done done.await(); + + // clean-up + for (AsynchronousSocketChannel ch: channels) + ch.close(); + for (AsynchronousChannelGroup group: groups) + group.shutdownNow(); + listener.close(); + if (failed.get()) throw new RuntimeException("Test failed - see log for details"); }
--- a/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -371,17 +371,22 @@ static void doMulticastTests() throws Exception { final byte[] msg = "hello".getBytes(); + InetAddress lh = InetAddress.getLocalHost(); + NetworkInterface interf = NetworkInterface.getByInetAddress(lh); + if (interf.isLoopback() || !interf.supportsMulticast()) { + System.out.println("Multicasting not tested"); + return; + } + AsynchronousDatagramChannel ch = AsynchronousDatagramChannel .open(StandardProtocolFamily.INET, null) .setOption(StandardSocketOption.SO_REUSEADDR, true) .bind(new InetSocketAddress(0)); - InetAddress lh = InetAddress.getLocalHost(); int port = ((InetSocketAddress)(ch.getLocalAddress())).getPort(); // join group InetAddress group = InetAddress.getByName("225.4.5.6"); - NetworkInterface interf = NetworkInterface.getByInetAddress(lh); MembershipKey key = ch.join(group, interf); // check key
--- a/test/java/nio/channels/AsynchronousFileChannel/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousFileChannel/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -45,16 +45,18 @@ File blah = File.createTempFile("blah", null); blah.deleteOnExit(); - final AsynchronousFileChannel ch = AsynchronousFileChannel + AsynchronousFileChannel ch = AsynchronousFileChannel .open(blah.toPath(), READ, WRITE); + try { + // run tests + testUsingCompletionHandlers(ch); + testUsingWaitOnResult(ch); + testInterruptHandlerThread(ch); + } finally { + ch.close(); + } - // run tests - testUsingCompletionHandlers(ch); - testUsingWaitOnResult(ch); - testInterruptHandlerThread(ch); - - // close channel and invoke test that expects channel to be closed - ch.close(); + // run test that expects channel to be closed testClosedChannel(ch); // these tests open the file themselves @@ -63,6 +65,9 @@ testAsynchronousClose(blah.toPath()); testCancel(blah.toPath()); testTruncate(blah.toPath()); + + // eagerly clean-up + blah.delete(); } /*
--- a/test/java/nio/channels/AsynchronousFileChannel/Lock.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousFileChannel/Lock.java Tue Jul 20 22:21:31 2010 -0700 @@ -53,13 +53,17 @@ LockSlaveMirror slave = startLockSlave(); try { - // create temporary file + // create temporary file File blah = File.createTempFile("blah", null); blah.deleteOnExit(); + // run tests testLockProtocol(blah, slave); testAsyncClose(blah, slave); + // eagerly clean-up + blah.delete(); + } finally { slave.shutdown(); } @@ -150,7 +154,12 @@ String sep = FileSystems.getDefault().getSeparator(); String command = System.getProperty("java.home") + - sep + "bin" + sep + "java Lock -lockslave " + port; + sep + "bin" + sep + "java"; + String testClasses = System.getProperty("test.classes"); + if (testClasses != null) + command += " -cp " + testClasses; + command += " Lock -lockslave " + port; + Process p = Runtime.getRuntime().exec(command); IOHandler.handle(p.getInputStream()); IOHandler.handle(p.getErrorStream());
--- a/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Tue Jul 20 22:21:31 2010 -0700 @@ -135,6 +135,7 @@ latch.await(); // verify content of each file + boolean failed = false; byte[] buf = new byte[8192]; for (int i=0; i<count ;i++) { Writer writer = writers[i]; @@ -145,18 +146,35 @@ int nread = in.read(buf); while (nread > 0) { for (int j=0; j<nread; j++) { - if (buf[j] != expected) - throw new RuntimeException("Unexpected byte"); + if (buf[j] != expected) { + System.err.println("Unexpected contents"); + failed = true; + break; + } expected++; } + if (failed) + break; size += nread; nread = in.read(buf); } - if (size != writer.size()) - throw new RuntimeException("Unexpected size"); + if (!failed && size != writer.size()) { + System.err.println("Unexpected size"); + failed = true; + } + if (failed) + break; } finally { in.close(); } } + + // clean-up + for (int i=0; i<count; i++) { + writers[i].file().delete(); + } + + if (failed) + throw new RuntimeException("Test failed"); } }
--- a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -776,6 +776,7 @@ throw new RuntimeException("RuntimeException expected after timeout."); ch.close(); + server.close(); } // returns ByteBuffer with random bytes
--- a/test/java/nio/channels/Channels/Basic2.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Channels/Basic2.java Tue Jul 20 22:21:31 2010 -0700 @@ -61,6 +61,9 @@ writerThread.join(); readerThread.join(); + // shutdown listener + listener.close(); + // check that reader received what we expected if (reader.total() != writer.total()) throw new RuntimeException("Unexpected number of bytes read");
--- a/test/java/nio/channels/Channels/Write.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Channels/Write.java Tue Jul 20 22:21:31 2010 -0700 @@ -47,5 +47,6 @@ out.close(); fc.close(); fos.close(); + testFile.delete(); } }
--- a/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Tue Jul 20 22:21:31 2010 -0700 @@ -82,8 +82,6 @@ } throw x; } - if (shouldTimeout) - throw new Exception("Receive did not time out"); break; }
--- a/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Tue Jul 20 22:21:31 2010 -0700 @@ -46,21 +46,25 @@ Thread serverThread = new Thread(server); serverThread.start(); DatagramChannel dc = DatagramChannel.open(); - ByteBuffer bb = ByteBuffer.allocateDirect(12); - bb.order(ByteOrder.BIG_ENDIAN); - bb.putInt(1).putLong(1); - bb.flip(); - InetAddress address = InetAddress.getLocalHost(); - InetSocketAddress isa = new InetSocketAddress(address, server.port()); - dc.connect(isa); - dc.write(bb); - bb.rewind(); - dc.write(bb); - bb.rewind(); - dc.write(bb); - Thread.sleep(2000); - serverThread.interrupt(); - server.throwException(); + try { + ByteBuffer bb = ByteBuffer.allocateDirect(12); + bb.order(ByteOrder.BIG_ENDIAN); + bb.putInt(1).putLong(1); + bb.flip(); + InetAddress address = InetAddress.getLocalHost(); + InetSocketAddress isa = new InetSocketAddress(address, server.port()); + dc.connect(isa); + dc.write(bb); + bb.rewind(); + dc.write(bb); + bb.rewind(); + dc.write(bb); + Thread.sleep(2000); + serverThread.interrupt(); + server.throwException(); + } finally { + dc.close(); + } } public static class Server implements Runnable { @@ -118,6 +122,8 @@ } } catch (Exception ex) { e = ex; + } finally { + try { dc.close(); } catch (IOException ignore) { } } } }
--- a/test/java/nio/channels/DatagramChannel/ReceiveISA.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/DatagramChannel/ReceiveISA.java Tue Jul 20 22:21:31 2010 -0700 @@ -66,6 +66,10 @@ rb.clear(); } + dc1.close(); + dc2.close(); + dc3.close(); + /* * Check that sa[0] equals sa[1] (both from dc1) * Check that sa[1] not equal to sa[2] (one from dc1, one from dc2)
--- a/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Tue Jul 20 22:21:31 2010 -0700 @@ -43,9 +43,9 @@ SocketAddress refuser = new InetSocketAddress(InetAddress.getLocalHost(), port); dc = DatagramChannel.open().bind(new InetSocketAddress(0)); + Selector sel = Selector.open(); try { dc.configureBlocking(false); - Selector sel = Selector.open(); dc.register(sel, SelectionKey.OP_READ); /* Test 1: not connected so ICMP port unreachable should not be received */ @@ -81,6 +81,7 @@ } } finally { + sel.close(); dc.close(); } }
--- a/test/java/nio/channels/FileChannel/Args.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Args.java Tue Jul 20 22:21:31 2010 -0700 @@ -97,6 +97,8 @@ (long)Integer.MAX_VALUE << 3); }}); + fc.close(); + f.delete(); } }
--- a/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Tue Jul 20 22:21:31 2010 -0700 @@ -38,6 +38,7 @@ test1(channel); test2(channel); channel.close(); + file.delete(); } static void test1(FileChannel channel) throws Exception {
--- a/test/java/nio/channels/FileChannel/ExpandingMap.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ExpandingMap.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,6 +25,7 @@ * @bug 4938372 6541641 * @summary Flushing dirty pages prior to unmap can cause Cleaner thread to * abort VM if memory system has pages locked + * @run main/othervm ExpandingMap */ import java.io.File; import java.io.RandomAccessFile;
--- a/test/java/nio/channels/FileChannel/Lock.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Lock.java Tue Jul 20 22:21:31 2010 -0700 @@ -55,6 +55,7 @@ test2(blah, true); test2(blah, false); test3(blah); + blah.delete(); } private static void test2(File blah, boolean b) throws Exception { @@ -90,7 +91,11 @@ // Exec the tamperer String command = System.getProperty("java.home") + - File.separator + "bin" + File.separator + "java Lock " + str + " " + blah; + File.separator + "bin" + File.separator + "java"; + String testClasses = System.getProperty("test.classes"); + if (testClasses != null) + command += " -cp " + testClasses; + command += " Lock " + str + " " + blah; Process p = Runtime.getRuntime().exec(command); BufferedReader in = new BufferedReader
--- a/test/java/nio/channels/FileChannel/MapOverEnd.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/MapOverEnd.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4463036 * @summary Check if file mapping extends beyond end of file + * @run main/othervm MapOverEnd */ import java.nio.*;
--- a/test/java/nio/channels/FileChannel/MapReadOnly.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/MapReadOnly.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4510489 * @summary Verify IOUtil.java reads to buffer limits + * @run main/othervm MapReadOnly */ import java.io.*; import java.nio.*;
--- a/test/java/nio/channels/FileChannel/MapTest.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/MapTest.java Tue Jul 20 22:21:31 2010 -0700 @@ -23,6 +23,7 @@ /* @test * @summary Test file mapping with FileChannel + * @run main/othervm MapTest */ import java.io.*;
--- a/test/java/nio/channels/FileChannel/Mode.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Mode.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test @bug 4462298 * @summary Test FileChannel maps with different accesses + * @run main/othervm Mode */ import java.nio.channels.*;
--- a/test/java/nio/channels/FileChannel/Position.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Position.java Tue Jul 20 22:21:31 2010 -0700 @@ -63,6 +63,7 @@ c.close(); fis.close(); + blah.delete(); } /**
--- a/test/java/nio/channels/FileChannel/Pread.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Pread.java Tue Jul 20 22:21:31 2010 -0700 @@ -65,6 +65,9 @@ throw new RuntimeException("Expected exception not thrown"); } catch(IllegalArgumentException e) { // Correct result + } finally { + fc.close(); + blah.delete(); } } @@ -73,13 +76,18 @@ File blah = File.createTempFile("blah2", null); blah.deleteOnExit(); FileOutputStream fos = new FileOutputStream(blah); - fos.write(new byte[128]); - FileChannel fc = fos.getChannel(); try { - fc.read(ByteBuffer.allocate(256),1); - throw new RuntimeException("Expected exception not thrown"); - } catch(NonReadableChannelException e) { - // Correct result + fos.write(new byte[128]); + FileChannel fc = fos.getChannel(); + try { + fc.read(ByteBuffer.allocate(256),1); + throw new RuntimeException("Expected exception not thrown"); + } catch(NonReadableChannelException e) { + // Correct result + } + } finally { + fos.close(); + blah.delete(); } } @@ -130,6 +138,7 @@ c.close(); fis.close(); + blah.delete(); } /**
--- a/test/java/nio/channels/FileChannel/Pwrite.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Pwrite.java Tue Jul 20 22:21:31 2010 -0700 @@ -62,6 +62,9 @@ throw new RuntimeException("Expected exception not thrown"); } catch(NonWritableChannelException e) { // Correct result + } finally { + fc.close(); + blah.delete(); } } @@ -123,6 +126,7 @@ } c.close(); raf.close(); + blah.delete(); } /**
--- a/test/java/nio/channels/FileChannel/Read.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Read.java Tue Jul 20 22:21:31 2010 -0700 @@ -80,6 +80,7 @@ c.close(); fis.close(); + blah.delete(); } /**
--- a/test/java/nio/channels/FileChannel/ReadFull.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ReadFull.java Tue Jul 20 22:21:31 2010 -0700 @@ -54,5 +54,6 @@ fc.close(); fis.close(); + blah.delete(); } }
--- a/test/java/nio/channels/FileChannel/ReadToLimit.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ReadToLimit.java Tue Jul 20 22:21:31 2010 -0700 @@ -48,6 +48,7 @@ throw new Exception("Test failed"); fc.close(); fis.close(); + blah.delete(); } /**
--- a/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Tue Jul 20 22:21:31 2010 -0700 @@ -39,8 +39,12 @@ public static void main(String[] args) throws IOException { File blah = File.createTempFile("blah", null); blah.deleteOnExit(); - for (int i=0; i<100; i++) { - test(blah.toPath()); + try { + for (int i=0; i<100; i++) { + test(blah.toPath()); + } + } finally { + blah.delete(); } }
--- a/test/java/nio/channels/FileChannel/ScatteringRead.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/ScatteringRead.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test @bug 4452020 4629048 4638365 4869859 * @summary Test FileChannel scattering reads + * @run main/othervm ScatteringRead */ import java.nio.channels.*;
--- a/test/java/nio/channels/FileChannel/Size.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Size.java Tue Jul 20 22:21:31 2010 -0700 @@ -24,6 +24,7 @@ /* @test * @bug 4563125 * @summary Test size method of FileChannel + * @run main/othervm Size */ import java.io.*;
--- a/test/java/nio/channels/FileChannel/Transfer.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Transfer.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,7 +25,6 @@ * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145 * @summary Test FileChannel.transferFrom and transferTo * @library .. - * @run main/timeout=180 Transfer */ import java.io.*; @@ -33,6 +32,8 @@ import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.SelectorProvider; +import java.nio.file.StandardOpenOption; +import java.nio.file.FileAlreadyExistsException; import java.util.Random; @@ -96,6 +97,9 @@ sourceChannel.close(); sinkChannel.close(); + + source.delete(); + sink.delete(); } private static void testReadableByteChannel(int size) throws Exception { @@ -139,6 +143,8 @@ fc.close(); sink.close(); source.close(); + + f.delete(); } public static void xferTest02() throws Exception { @@ -173,6 +179,9 @@ fc2.close(); raf1.close(); raf2.close(); + + source.delete(); + dest.delete(); } public static void xferTest03() throws Exception { @@ -207,6 +216,9 @@ fc2.close(); raf1.close(); raf2.close(); + + source.delete(); + dest.delete(); } // Test transferTo with large file @@ -245,27 +257,36 @@ sourceChannel.close(); sinkChannel.close(); + source.delete(); + sink.delete(); } // Test transferFrom with large file public static void xferTest05() throws Exception { - // Linux can't handle the really large file sizes for a - // truncate or a positional write - String osName = System.getProperty("os.name"); - if (osName.startsWith("Linux")) - return; - // Create a source file & large sink file for the test File source = File.createTempFile("blech", null); source.deleteOnExit(); initTestFile(source, 100); - File sink = File.createTempFile("sink", null); + // Create the sink file as a sparse file if possible + File sink = null; + FileChannel fc = null; + while (fc == null) { + sink = File.createTempFile("sink", null); + // re-create as a sparse file + sink.toPath().delete(); + try { + fc = FileChannel.open(sink.toPath(), + StandardOpenOption.CREATE_NEW, + StandardOpenOption.WRITE, + StandardOpenOption.SPARSE); + } catch (FileAlreadyExistsException ignore) { + // someone else got it + } + } sink.deleteOnExit(); long testSize = ((long)Integer.MAX_VALUE) * 2; - RandomAccessFile raf = new RandomAccessFile(sink, "rw"); - FileChannel fc = raf.getChannel(); try { fc.write(ByteBuffer.wrap("Use the source!".getBytes()), testSize - 40); @@ -275,24 +296,28 @@ return; } finally { fc.close(); - raf.close(); } // Get new channels for the source and sink and attempt transfer - FileInputStream fis = new FileInputStream(source); - FileChannel sourceChannel = fis.getChannel(); - - raf = new RandomAccessFile(sink, "rw"); - FileChannel sinkChannel = raf.getChannel(); + FileChannel sourceChannel = new FileInputStream(source).getChannel(); + try { + FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel(); + try { + long bytesWritten = sinkChannel.transferFrom(sourceChannel, + testSize - 40, 10); + if (bytesWritten != 10) { + throw new RuntimeException("Transfer test 5 failed " + + bytesWritten); + } + } finally { + sinkChannel.close(); + } + } finally { + sourceChannel.close(); + } - long bytesWritten = sinkChannel.transferFrom(sourceChannel, - testSize - 40, 10); - if (bytesWritten != 10) { - throw new RuntimeException("Transfer test 5 failed " + - bytesWritten); - } - sourceChannel.close(); - sinkChannel.close(); + source.delete(); + sink.delete(); } static void checkFileData(File file, String expected) throws Exception { @@ -338,6 +363,8 @@ checkFileData(source, data); checkFileData(sink, data.substring(7,data.length())); + + source.delete(); } // Test transferTo to non-blocking socket channel @@ -371,6 +398,7 @@ sink.close(); other.close(); ssc.close(); + source.delete(); } @@ -473,6 +501,7 @@ source.close(); ssc.close(); fc.close(); + file.delete(); } }
--- a/test/java/nio/channels/FileChannel/TransferToChannel.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/TransferToChannel.java Tue Jul 20 22:21:31 2010 -0700 @@ -51,6 +51,8 @@ test1(); test2(); in.close(); + file.delete(); + outFile.delete(); } static void test1() throws Exception {
--- a/test/java/nio/channels/FileChannel/TransferToNonWritable.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/TransferToNonWritable.java Tue Jul 20 22:21:31 2010 -0700 @@ -43,6 +43,9 @@ throw new RuntimeException("Test failed"); } catch (NonWritableChannelException nwce) { // Correct result + } finally { + channel.close(); + blah.delete(); } } }
--- a/test/java/nio/channels/FileChannel/Transfers.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Transfers.java Tue Jul 20 22:21:31 2010 -0700 @@ -554,6 +554,10 @@ break; } + sourceFile.delete(); + targetFile.delete(); + fn.delete(); + if (failures > 0) { out.println(); throw new RuntimeException("Some tests failed");
--- a/test/java/nio/channels/FileChannel/TryLock.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/TryLock.java Tue Jul 20 22:21:31 2010 -0700 @@ -56,7 +56,6 @@ public static void test1(boolean shared, boolean trylock) throws Exception { File testFile = File.createTempFile("test1", null); - testFile.deleteOnExit(); FileInputStream fis = new FileInputStream(testFile); FileChannel fc = fis.getChannel(); FileLock fl = null; @@ -73,12 +72,13 @@ } finally { if (fl != null) fl.release(); + fc.close(); + testFile.delete(); } } public static void test2(boolean shared, boolean trylock) throws Exception { File testFile = File.createTempFile("test2", null); - testFile.deleteOnExit(); FileOutputStream fis = new FileOutputStream(testFile); FileChannel fc = fis.getChannel(); FileLock fl = null; @@ -95,19 +95,25 @@ } finally { if (fl != null) fl.release(); + fc.close(); + testFile.delete(); } } public static void test3(boolean shared, boolean trylock) throws Exception { File testFile = File.createTempFile("test3", null); - testFile.deleteOnExit(); RandomAccessFile fis = new RandomAccessFile(testFile, "rw"); FileChannel fc = fis.getChannel(); - FileLock fl = null; - if (trylock) - fl = fc.tryLock(0, fc.size(), shared); - else - fl = fc.lock(0, fc.size(), shared); - fl.release(); + try { + FileLock fl = null; + if (trylock) + fl = fc.tryLock(0, fc.size(), shared); + else + fl = fc.lock(0, fc.size(), shared); + fl.release(); + } finally { + fc.close(); + testFile.delete(); + } } }
--- a/test/java/nio/channels/FileChannel/Write.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/FileChannel/Write.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,6 +25,7 @@ * @test * @bug 4475533 4698138 4638365 4796221 * @summary Test FileChannel write + * @run main/othervm Write */ import java.nio.channels.*; @@ -46,23 +47,25 @@ // Test to see that offset > length does not throw exception static void test1() throws Exception { - File testFile = File.createTempFile("test1", null); - testFile.deleteOnExit(); - ByteBuffer[] dsts = new ByteBuffer[4]; for (int i=0; i<4; i++) dsts[i] = ByteBuffer.allocateDirect(10); - FileOutputStream fos = new FileOutputStream(testFile); - FileChannel fc = fos.getChannel(); - fc.write(dsts, 2, 1); - fos.close(); + File testFile = File.createTempFile("test1", null); + try { + FileOutputStream fos = new FileOutputStream(testFile); + FileChannel fc = fos.getChannel(); + fc.write(dsts, 2, 1); + fos.close(); + } finally { + testFile.delete(); + } } // Test to see that the appropriate buffers are updated static void test2() throws Exception { File testFile = File.createTempFile("test2", null); - testFile.deleteOnExit(); + testFile.delete(); ByteBuffer[] srcs = new ByteBuffer[4]; for (int i=0; i<4; i++) srcs[i] = ByteBuffer.allocateDirect(10); @@ -74,25 +77,34 @@ FileOutputStream fos = new FileOutputStream(testFile); FileChannel fc = fos.getChannel(); - fc.write(srcs, 1, 2); - fos.close(); + try { + fc.write(srcs, 1, 2); + } finally { + fc.close(); + } FileInputStream fis = new FileInputStream(testFile); fc = fis.getChannel(); - ByteBuffer bb = ByteBuffer.allocateDirect(10); - fc.read(bb); - bb.flip(); - if (bb.get() != 2) - throw new RuntimeException("Write failure"); - if (bb.get() != 3) - throw new RuntimeException("Write failure"); try { - bb.get(); - throw new RuntimeException("Write failure"); - } catch (BufferUnderflowException bufe) { - // correct result + ByteBuffer bb = ByteBuffer.allocateDirect(10); + fc.read(bb); + bb.flip(); + if (bb.get() != 2) + throw new RuntimeException("Write failure"); + if (bb.get() != 3) + throw new RuntimeException("Write failure"); + try { + bb.get(); + throw new RuntimeException("Write failure"); + } catch (BufferUnderflowException bufe) { + // correct result + } + } finally { + fc.close(); } - fis.close(); + + // eagerly clean-up + testFile.delete(); } // Test write to a negative position (bug 4698138).
--- a/test/java/nio/channels/Pipe/NonBlocking.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Pipe/NonBlocking.java Tue Jul 20 22:21:31 2010 -0700 @@ -41,12 +41,17 @@ static void test1() throws Exception { Pipe p = Pipe.open(); - p.sink().configureBlocking(false); - if (p.sink().isBlocking()) - throw new Exception("Sink still blocking"); - p.source().configureBlocking(false); - if (p.source().isBlocking()) - throw new Exception("Source still blocking"); + try { + p.sink().configureBlocking(false); + if (p.sink().isBlocking()) + throw new Exception("Sink still blocking"); + p.source().configureBlocking(false); + if (p.source().isBlocking()) + throw new Exception("Source still blocking"); + } finally { + p.sink().close(); + p.source().close(); + } } }
--- a/test/java/nio/channels/Pipe/SelectPipe.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Pipe/SelectPipe.java Tue Jul 20 22:21:31 2010 -0700 @@ -78,10 +78,12 @@ totalRead += bytesRead; } while(totalRead < 10); + sink.close(); + source.close(); + selector.close(); + for(int i=0; i<10; i++) if (outgoingdata.get(i) != incomingdata.get(i)) throw new Exception("Pipe failed"); - sink.close(); - source.close(); } }
--- a/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Tue Jul 20 22:21:31 2010 -0700 @@ -58,6 +58,11 @@ }; t.join(); + + pipe.sink().close(); + pipe.source().close(); + selector.close(); + int count = errorCount.get(); if (count > 0) { throw new RuntimeException("Error count:" + count);
--- a/test/java/nio/channels/Selector/BasicAccept.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/BasicAccept.java Tue Jul 20 22:21:31 2010 -0700 @@ -36,49 +36,60 @@ public class BasicAccept { - public static int TEST_PORT = 40170; - - static void server() throws Exception { + static void server(ServerSocketChannel ssc) throws Exception { Selector acceptSelector = Selector.open(); - ServerSocketChannel ssc = ServerSocketChannel.open(); - ssc.configureBlocking(false); - InetAddress lh = InetAddress.getLocalHost(); - InetSocketAddress isa - = new InetSocketAddress(lh, SelectorTest.TEST_PORT); - ssc.socket().bind(isa); - SelectionKey acceptKey - = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT); - for (;;) { - if (acceptSelector.select() == 0) - continue; - Set readyKeys = acceptSelector.selectedKeys(); - Iterator i = readyKeys.iterator(); - while (i.hasNext()) { - SelectionKey sk = (SelectionKey)i.next(); - i.remove(); - ServerSocketChannel nextReady - = (ServerSocketChannel)sk.channel(); - SocketChannel sc = nextReady.accept(); - ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 }); - sc.write(bb); + try { + ssc.configureBlocking(false); + SelectionKey acceptKey + = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT); + for (;;) { + int n = acceptSelector.select(); + if (Thread.interrupted()) + break; + if (n == 0) + continue; + Set<SelectionKey> readyKeys = acceptSelector.selectedKeys(); + Iterator<SelectionKey> i = readyKeys.iterator(); + while (i.hasNext()) { + SelectionKey sk = i.next(); + i.remove(); + ServerSocketChannel nextReady + = (ServerSocketChannel)sk.channel(); + SocketChannel sc = nextReady.accept(); + ByteBuffer bb = ByteBuffer.wrap(new byte[] { 42 }); + sc.write(bb); + sc.close(); + } + } + } finally { + acceptSelector.close(); + } + } + + private static class Server extends TestThread { + final ServerSocketChannel ssc; + Server() throws IOException { + super("Server", System.err); + this.ssc = ServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + } + int port() { + return ssc.socket().getLocalPort(); + } + void go() throws Exception { + try { + server(ssc); + } finally { + ssc.close(); } } } - private static class Server extends TestThread { - Server() { - super("Server", System.err); - } - void go() throws Exception { - server(); - } - } - - static void client() throws Exception { + static void client(int port) throws Exception { // Get a connection from the server InetAddress lh = InetAddress.getLocalHost(); InetSocketAddress isa - = new InetSocketAddress(lh, SelectorTest.TEST_PORT); + = new InetSocketAddress(lh, port); int connectFailures = 0; boolean result = false; SocketChannel sc = SocketChannel.open(); @@ -122,17 +133,17 @@ if (bb.get(0) != 42) throw new RuntimeException("Read wrong byte from server"); System.err.println("Read from server"); + sc.close(); } public static void main(String[] args) throws Exception { - if (args.length == 0) { - Server server = new Server(); - server.start(); - client(); - } else if (args[0].equals("client")) { - client(); - } else if (args[0].equals("server")) { - server(); + Server server = new Server(); + server.start(); + try { + client(server.port()); + } finally { + server.interrupt(); + server.finish(2000); } }
--- a/test/java/nio/channels/Selector/BasicConnect.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/BasicConnect.java Tue Jul 20 22:21:31 2010 -0700 @@ -83,10 +83,13 @@ ByteBuffer bb2 = ByteBuffer.allocateDirect(100); int n = sc.read(bb2); bb2.flip(); + + sc.close(); + connectSelector.close(); + if (!bb.equals(bb2)) throw new Exception("Echoed bytes incorrect: Sent " + bb + ", got " + bb2); - sc.close(); } }
--- a/test/java/nio/channels/Selector/CheckLocking.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/CheckLocking.java Tue Jul 20 22:21:31 2010 -0700 @@ -61,5 +61,7 @@ doSelect(); sk.interestOps(SelectionKey.OP_READ); selector.wakeup(); + sc.close(); + selector.close(); } }
--- a/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Tue Jul 20 22:21:31 2010 -0700 @@ -33,12 +33,16 @@ public static void main (String [] args) throws Exception { DatagramChannel ch = DatagramChannel.open(); - ch.configureBlocking(false); - Selector sel = Selector.open(); - SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE); - sel.close(); - if (key.isValid()) - throw new Exception("Key valid after selector closed"); + try { + ch.configureBlocking(false); + Selector sel = Selector.open(); + SelectionKey key = ch.register(sel, SelectionKey.OP_WRITE); + sel.close(); + if (key.isValid()) + throw new Exception("Key valid after selector closed"); + } finally { + ch.close(); + } } }
--- a/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Tue Jul 20 22:21:31 2010 -0700 @@ -111,10 +111,14 @@ // select should block int spinCount = 0; + boolean failed = false; for (;;) { int n = sel.select(); - if (n > 0) - throw new RuntimeException("channel should not be selected"); + if (n > 0) { + System.err.println("Channel should not be selected!!!"); + failed = true; + break; + } // wakeup if (wakeupDone) @@ -123,10 +127,19 @@ // wakeup for no reason - if it happens a few times then we have a // problem spinCount++; - if (spinCount >= 3) - throw new RuntimeException("Selector appears to be spinning"); + if (spinCount >= 3) { + System.err.println("Selector appears to be spinning"); + failed = true; + break; + } } + sc1.close(); + sel.close(); + + if (failed) + throw new RuntimeException("Test failed"); + System.out.println("PASS"); }
--- a/test/java/nio/channels/Selector/Connect.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/Connect.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,7 +25,6 @@ * @bug 4511624 * @summary Test Making lots of Selectors * @library .. - * @run main/timeout=240 Connect */ import java.io.*; @@ -38,7 +37,7 @@ public class Connect { static int success = 0; - static int LIMIT = 500; + static int LIMIT = 100; public static void main(String[] args) throws Exception { scaleTest(); @@ -51,29 +50,30 @@ for (int j=0; j<LIMIT; j++) { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); - boolean result = sc.connect(isa); - if (!result) { + boolean connected = sc.connect(isa); + if (!connected) { Selector RSelector = SelectorProvider.provider().openSelector(); SelectionKey RKey = sc.register (RSelector, SelectionKey.OP_CONNECT); - while (!result) { + while (!connected) { int keysAdded = RSelector.select(100); if (keysAdded > 0) { - Set readyKeys = RSelector.selectedKeys(); - Iterator i = readyKeys.iterator(); + Set<SelectionKey> readyKeys = RSelector.selectedKeys(); + Iterator<SelectionKey> i = readyKeys.iterator(); while (i.hasNext()) { - SelectionKey sk = (SelectionKey)i.next(); + SelectionKey sk = i.next(); SocketChannel nextReady = (SocketChannel)sk.channel(); - result = nextReady.finishConnect(); + connected = nextReady.finishConnect(); } + readyKeys.clear(); } } RSelector.close(); } - read(sc); + readAndClose(sc); } } - static void read(SocketChannel sc) throws Exception { + static void readAndClose(SocketChannel sc) throws Exception { ByteBuffer bb = ByteBuffer.allocateDirect(100); int n = 0; while (n == 0) // Note this is not a rigorous check for done reading
--- a/test/java/nio/channels/Selector/ConnectWrite.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/ConnectWrite.java Tue Jul 20 22:21:31 2010 -0700 @@ -45,8 +45,8 @@ Selector selector = SelectorProvider.provider().openSelector(); InetAddress myAddress=InetAddress.getByName(TestUtil.HOST); InetSocketAddress isa = new InetSocketAddress(myAddress, port); + SocketChannel sc = SocketChannel.open(); try { - SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); boolean result = sc.connect(isa); @@ -80,6 +80,7 @@ } } } finally { + sc.close(); selector.close(); } }
--- a/test/java/nio/channels/Selector/HelperSlowToDie.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/HelperSlowToDie.java Tue Jul 20 22:21:31 2010 -0700 @@ -33,9 +33,15 @@ public class HelperSlowToDie { private static final int CHANNELS_PER_THREAD = 1023; + private static final int TEST_ITERATIONS = 200; private static volatile boolean done; public static void main(String[] args) throws IOException { + if (!System.getProperty("os.name").startsWith("Windows")) { + System.out.println("Test skipped as it verifies a Windows specific bug"); + return; + } + Selector sel = Selector.open(); // register channels @@ -60,7 +66,7 @@ new Thread(busy).start(); // Loop changing the number of channels from 1023 to 1024 and back. - for (int i=0; i<1000; i++) { + for (int i=0; i<TEST_ITERATIONS; i++) { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); sc.register(sel, SelectionKey.OP_CONNECT); @@ -71,5 +77,11 @@ // terminate busy threads done = true; + + // clean-up + for (int i=0; i<CHANNELS_PER_THREAD; i++) { + channels[i].close(); + } + sel.close(); } }
--- a/test/java/nio/channels/Selector/KeysReady.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/KeysReady.java Tue Jul 20 22:21:31 2010 -0700 @@ -49,14 +49,18 @@ // Prepare a selector Selector selector = SelectorProvider.provider().openSelector(); - SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); - int keysAdded = selector.select(); - if (keysAdded > 0) { - keysAdded = selector.select(1000); - if (keysAdded > 0) - throw new Exception("Same key reported added twice"); + try { + SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); + int keysAdded = selector.select(); + if (keysAdded > 0) { + keysAdded = selector.select(1000); + if (keysAdded > 0) + throw new Exception("Same key reported added twice"); + } + } finally { + selector.close(); + sc.close(); } - sc.close(); } public static void main(String[] args) throws Exception {
--- a/test/java/nio/channels/Selector/LotsOfChannels.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/LotsOfChannels.java Tue Jul 20 22:21:31 2010 -0700 @@ -35,19 +35,11 @@ public class LotsOfChannels { - private final static int PIPES_COUNT = 1900; + private final static int PIPES_COUNT = 256; private final static int BUF_SIZE = 8192; private final static int LOOPS = 10; public static void main(String[] argv) throws Exception { - - - String os = System.getProperty("os.name"); - if (!(os.equals("Windows NT") - || os.equals("Windows 2000") - || os.equals("Windows XP"))) - return; - Pipe[] pipes = new Pipe[PIPES_COUNT]; Pipe pipe = Pipe.open(); Pipe.SinkChannel sink = pipe.sink(); @@ -72,6 +64,13 @@ sel.selectedKeys().clear(); source.read(ByteBuffer.allocate(BUF_SIZE)); } + + for (int i = 0; i < PIPES_COUNT; i++ ) { + pipes[i].sink().close(); + pipes[i].source().close(); + } + pipe.sink().close(); + pipe.source().close(); sel.close(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/nio/channels/Selector/OutOfBand.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 6213702 + * @summary OOB data causes a SocketChannel, with OOBINLINE disabled, to be + * selected + */ + +import java.net.*; +import java.nio.ByteBuffer; +import java.nio.channels.*; +import java.io.IOException; + +public class OutOfBand { + + public static void main(String[] args) throws Exception { + ServerSocketChannel ssc = null; + SocketChannel sc = null; + Selector sel = null; + Socket s = null; + + try { + // establish loopback connection. + ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0)); + s = new Socket(InetAddress.getLocalHost(), + ssc.socket().getLocalPort()); + sc = ssc.accept(); + + sel = Selector.open(); + sc.configureBlocking(false); + sc.register(sel, SelectionKey.OP_READ); + + // OOB data should be disabled by default + if (sc.socket().getOOBInline()) + throw new RuntimeException("SO_OOBINLINE enabled"); + test(s, false, 0, 0, sel); + test(s, false, 512, 0, sel); + test(s, false, 0, 512, sel); + test(s, false, 512, 512, sel); + + // enable SO_OOBINLINE + sc.socket().setOOBInline(true); + + // OOB data should be received + test(s, true, 0, 0, sel); + test(s, true, 512, 0, sel); + test(s, true, 0, 512, sel); + test(s, true, 512, 512, sel); + + } finally { + if (sel != null) sel.close(); + if (sc != null) sc.close(); + if (ssc != null) ssc.close(); + if (s != null) sc.close(); + } + } + + static void test(Socket s, boolean urgentExpected, + int bytesBefore, int bytesAfter, + Selector sel) + throws IOException + { + // send data + int bytesExpected = 0; + if (bytesBefore > 0) { + s.getOutputStream().write(new byte[bytesBefore]); + bytesExpected += bytesBefore; + } + s.sendUrgentData(0xff); + if (urgentExpected) + bytesExpected++; + if (bytesAfter > 0) { + s.getOutputStream().write(new byte[bytesAfter]); + bytesExpected += bytesAfter; + } + + // receive data, checking for spurious wakeups and reads + int spuriousWakeups = 0; + int spuriousReads = 0; + int bytesRead = 0; + ByteBuffer bb = ByteBuffer.allocate(100); + for (;;) { + int n = sel.select(2000); + if (n == 0) { + if (bytesRead == bytesExpected) { + System.out.format("Selector wakeups %d\tSpurious reads %d%n", + spuriousWakeups, spuriousReads); + return; + } + if (++spuriousWakeups >= 3) + throw new RuntimeException("Selector appears to be spinning" + + " or data not received"); + continue; + } + if (n > 1) + throw new RuntimeException("More than one key selected????"); + SelectionKey key = sel.selectedKeys().iterator().next(); + bb.clear(); + n = ((SocketChannel)key.channel()).read(bb); + if (n == 0) { + if (++spuriousReads >=3) + throw new RuntimeException("Too many spurious reads"); + } else { + bytesRead += n; + if (bytesRead > bytesExpected) + throw new RuntimeException("Received more than expected"); + } + sel.selectedKeys().clear(); + } + } +}
--- a/test/java/nio/channels/Selector/RegAfterPreClose.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/RegAfterPreClose.java Tue Jul 20 22:21:31 2010 -0700 @@ -35,6 +35,7 @@ public class RegAfterPreClose { + static final int TEST_ITERATIONS = 300; static volatile boolean done; /** @@ -96,26 +97,21 @@ } }; - // schedule test to run for 1 minute - Executors.newScheduledThreadPool(1, factory).schedule(new Runnable() { - public void run() { - done = true; - sel.wakeup(); - }}, 1, TimeUnit.MINUTES); - // create Executor that handles tasks that closes channels // "asynchronously" - this creates the conditions to provoke the bug. - Executor executor = Executors.newFixedThreadPool(2, factory); + ExecutorService executor = Executors.newFixedThreadPool(2, factory); // submit task that connects to listener executor.execute(new Connector(ssc.socket().getLocalPort())); // loop accepting connections until done (or an IOException is thrown) - while (!done) { + int remaining = TEST_ITERATIONS; + while (remaining > 0) { sel.select(); if (key.isAcceptable()) { SocketChannel sc = ssc.accept(); if (sc != null) { + remaining--; sc.configureBlocking(false); sc.register(sel, SelectionKey.OP_READ); executor.execute(new Closer(sc)); @@ -123,5 +119,8 @@ } sel.selectedKeys().clear(); } + done = true; + sel.close(); + executor.shutdown(); } }
--- a/test/java/nio/channels/Selector/SelectAndCancel.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/SelectAndCancel.java Tue Jul 20 22:21:31 2010 -0700 @@ -31,11 +31,7 @@ import java.net.*; public class SelectAndCancel { - static ServerSocketChannel ssc; - static Selector selector; static SelectionKey sk; - static InetSocketAddress isa; - public static int TEST_PORT = 40170; /* * CancelledKeyException is the failure symptom of 4729342 @@ -43,17 +39,17 @@ * seen immediately when the bug is present. */ public static void main(String[] args) throws Exception { - InetAddress lh = InetAddress.getLocalHost(); - isa = new InetSocketAddress(lh, TEST_PORT); - selector = Selector.open(); - ssc = ServerSocketChannel.open(); + final Selector selector = Selector.open(); + final ServerSocketChannel ssc = + ServerSocketChannel.open().bind(new InetSocketAddress(0)); + final InetSocketAddress isa = + new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort()); // Create and start a selector in a separate thread. new Thread(new Runnable() { public void run() { try { ssc.configureBlocking(false); - ssc.socket().bind(isa); sk = ssc.register(selector, SelectionKey.OP_ACCEPT); selector.select(); } catch (IOException e) {
--- a/test/java/nio/channels/Selector/SelectorLimit.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/SelectorLimit.java Tue Jul 20 22:21:31 2010 -0700 @@ -26,6 +26,8 @@ * @summary Ensure that a Selector can return at least 100 selected keys * @author Mark Reinhold * @library .. + * @build SelectorLimit + * @run main/othervm SelectorLimit */ import java.io.*;
--- a/test/java/nio/channels/Selector/SelectorTest.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/SelectorTest.java Tue Jul 20 22:21:31 2010 -0700 @@ -57,13 +57,13 @@ */ public static void main(String[] args) throws Exception { if (args.length == 0) { - InetSocketAddress isa - = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT); - Server server = new Server(isa); + Server server = new Server(0); server.start(); try { Thread.sleep(1000); } catch (InterruptedException e) { } + InetSocketAddress isa + = new InetSocketAddress(InetAddress.getLocalHost(), server.port()); Client client = new Client(isa); client.start(); if ((server.finish(FINISH_TIME) & client.finish(FINISH_TIME)) == 0) @@ -74,9 +74,7 @@ if (args.length > 1) TEST_PORT = Integer.parseInt(args[1]); - InetSocketAddress isa - = new InetSocketAddress(InetAddress.getLocalHost(), TEST_PORT); - Server server = new Server(isa); + Server server = new Server(TEST_PORT); server.start(); if (server.finish(FINISH_TIME) == 0) throw new Exception("Failure"); @@ -136,18 +134,22 @@ } static class Server extends TestThread { + private final ServerSocketChannel ssc; private List socketList = new ArrayList(); private ServerSocket ss; private int connectionsAccepted = 0; private Selector pollSelector; private Selector acceptSelector; - private InetSocketAddress isa; private Set pkeys; private Set pskeys; - Server(InetSocketAddress isa) { + Server(int port) throws IOException { super("Server", SelectorTest.log); - this.isa = isa; + this.ssc = ServerSocketChannel.open().bind(new InetSocketAddress(port)); + } + + int port() { + return ssc.socket().getLocalPort(); } public void go() throws Exception { @@ -162,11 +164,7 @@ requestThread.start(); - ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); - ssc.socket().setReuseAddress(true); - ssc.socket().bind(isa); - SelectionKey acceptKey = ssc.register(acceptSelector, SelectionKey.OP_ACCEPT); while(connectionsAccepted < SelectorTest.NUM_CLIENTS) {
--- a/test/java/nio/channels/Selector/WakeupNow.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/WakeupNow.java Tue Jul 20 22:21:31 2010 -0700 @@ -44,10 +44,15 @@ p.source().configureBlocking(false); p.source().register(sel, SelectionKey.OP_READ); sel.wakeup(); + // ensure wakeup is consumed by selectNow + Thread.sleep(2000); sel.selectNow(); long startTime = System.currentTimeMillis(); int n = sel.select(2000); long endTime = System.currentTimeMillis(); + p.source().close(); + p.sink().close(); + sel.close(); if (endTime - startTime < 1000) throw new RuntimeException("test failed"); } @@ -60,10 +65,13 @@ Pipe p = Pipe.open(); p.source().configureBlocking(false); sel.wakeup(); + // ensure wakeup is consumed by selectNow + Thread.sleep(2000); sel.selectNow(); long startTime = System.currentTimeMillis(); int n = sel.select(2000); long endTime = System.currentTimeMillis(); + sel.close(); if (endTime - startTime < 1000) throw new RuntimeException("test failed"); }
--- a/test/java/nio/channels/Selector/WakeupOverflow.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/WakeupOverflow.java Tue Jul 20 22:21:31 2010 -0700 @@ -31,8 +31,12 @@ public class WakeupOverflow { public static void main( String[] args ) throws Exception { Selector selector = Selector.open(); - for(int i=0; i<10000; i++) { - selector.wakeup(); + try { + for(int i=0; i<10000; i++) { + selector.wakeup(); + } + } finally { + selector.close(); } } }
--- a/test/java/nio/channels/Selector/WakeupSpeed.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/Selector/WakeupSpeed.java Tue Jul 20 22:21:31 2010 -0700 @@ -35,16 +35,19 @@ public static void main(String argv[]) throws Exception { int waitTime = 4000; Selector selector = Selector.open(); - - selector.wakeup(); + try { + selector.wakeup(); - long t1 = System.currentTimeMillis(); - selector.select(waitTime); - long t2 = System.currentTimeMillis(); - long totalTime = t2 - t1; + long t1 = System.currentTimeMillis(); + selector.select(waitTime); + long t2 = System.currentTimeMillis(); + long totalTime = t2 - t1; - if (totalTime > waitTime) - throw new RuntimeException("Test failed"); + if (totalTime > waitTime) + throw new RuntimeException("Test failed"); + } finally { + selector.close(); + } } }
--- a/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java Thu Jul 15 20:11:45 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @summary test the address returned in socket from accept - */ - -import java.io.*; -import java.net.*; -import java.nio.*; -import java.nio.channels.*; - - -public class AcceptAddress { - - public static void main(String[] args) throws Exception { - InetAddress local = InetAddress.getLocalHost(); - InetSocketAddress isa = new InetSocketAddress(local, 5555); - - ServerSocketChannel ssc; - ssc = ServerSocketChannel.open(); - ssc.socket().bind(isa); - - SocketChannel sc; - sc = SocketChannel.open(); - sc.connect(isa); - - SocketChannel sc2 = ssc.accept(); - System.err.println("Socket connected to " + sc2); - } -}
--- a/test/java/nio/channels/SocketChannel/AdaptSocket.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/AdaptSocket.java Tue Jul 20 22:21:31 2010 -0700 @@ -78,8 +78,6 @@ throw x; } } - if (shouldTimeout) - throw new Exception("Connection did not time out"); } out.println("connected: " + so); out.println(" " + sc); @@ -118,8 +116,6 @@ } throw x; } - if (shouldTimeout) - throw new Exception("Read did not time out"); } static void testRead(String hn, int timeout, boolean shouldTimeout)
--- a/test/java/nio/channels/SocketChannel/Bind.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/Bind.java Tue Jul 20 22:21:31 2010 -0700 @@ -31,13 +31,20 @@ public class Bind { public static void main(String[] args) throws Exception { + SocketChannel sc1 = SocketChannel.open(); try { - SocketChannel channel1 = SocketChannel.open(); - channel1.socket().bind(new InetSocketAddress(5555)); - SocketChannel channel2 = SocketChannel.open(); - channel2.socket().bind(new InetSocketAddress(5555)); + sc1.bind(new InetSocketAddress(0)); + int port = sc1.socket().getLocalPort(); + SocketChannel sc2 = SocketChannel.open(); + try { + sc2.bind(new InetSocketAddress(port)); + } finally { + sc2.close(); + } } catch (BindException be) { // Correct result + } finally { + sc1.close(); } } }
--- a/test/java/nio/channels/SocketChannel/Close.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/Close.java Tue Jul 20 22:21:31 2010 -0700 @@ -56,8 +56,12 @@ static void testChannelClose() throws IOException { SelectionKey sk = open(); - sk.channel().close(); - check(sk); + try { + sk.channel().close(); + check(sk); + } finally { + sk.selector().close(); + } } public static void main(String[] args) throws Exception {
--- a/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Tue Jul 20 22:21:31 2010 -0700 @@ -55,5 +55,8 @@ System.out.println ("Will hang here..."); int nb = slave.read (ByteBuffer.allocate (1024)); //System.out.println("read nb=" + nb); + + selector.close(); + server.close(); } }
--- a/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Tue Jul 20 22:21:31 2010 -0700 @@ -33,11 +33,12 @@ import java.net.*; public class CloseTimeoutChannel { - final static int PORT=6347; public static void main(String args[]) throws Exception { + int port = -1; try { ServerSocketChannel listener=ServerSocketChannel.open(); - listener.socket().bind(new InetSocketAddress(PORT)); + listener.socket().bind(new InetSocketAddress(0)); + port = listener.socket().getLocalPort(); AcceptorThread thread=new AcceptorThread(listener); thread.start(); } catch (IOException e) { @@ -50,7 +51,7 @@ try { System.out.println("Establishing connection"); Socket socket=SocketChannel.open( - new InetSocketAddress("127.0.0.1", PORT)).socket(); + new InetSocketAddress("127.0.0.1", port)).socket(); OutputStream out=socket.getOutputStream(); InputStream in=socket.getInputStream(); @@ -98,7 +99,8 @@ Thread.sleep(100); } catch (InterruptedException e) { } - System.out.println(INDENT+"Listening on port "+ PORT); + System.out.println(INDENT+"Listening on port "+ + _listener.socket().getLocalPort()); ByteBuffer buf=ByteBuffer.allocate(5); Socket client=_listener.accept().socket();; System.out.println(INDENT+"Accepted client"); @@ -123,6 +125,8 @@ client.close(); } catch (IOException e) { System.out.println(INDENT+"Error accepting!"); + } finally { + try { _listener.close(); } catch (IOException ignore) { } } } }
--- a/test/java/nio/channels/SocketChannel/IsConnectable.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/IsConnectable.java Tue Jul 20 22:21:31 2010 -0700 @@ -48,27 +48,31 @@ sc.connect(isa); Selector selector = SelectorProvider.provider().openSelector(); - SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); - int keysAdded = selector.select(); - if (keysAdded > 0) { - boolean result = sc.finishConnect(); - if (result) { - keysAdded = selector.select(5000); - // 4750573: keysAdded should not be incremented when op is dropped - // from a key already in the selected key set - if (keysAdded > 0) - throw new Exception("Test failed: 4750573 detected"); - Set sel = selector.selectedKeys(); - Iterator i = sel.iterator(); - SelectionKey sk = (SelectionKey)i.next(); - // 4737146: isConnectable should be false while connected - if (sk.isConnectable()) - throw new Exception("Test failed: 4737146 detected"); + try { + SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); + int keysAdded = selector.select(); + if (keysAdded > 0) { + boolean result = sc.finishConnect(); + if (result) { + keysAdded = selector.select(5000); + // 4750573: keysAdded should not be incremented when op is dropped + // from a key already in the selected key set + if (keysAdded > 0) + throw new Exception("Test failed: 4750573 detected"); + Set<SelectionKey> sel = selector.selectedKeys(); + Iterator<SelectionKey> i = sel.iterator(); + SelectionKey sk = i.next(); + // 4737146: isConnectable should be false while connected + if (sk.isConnectable()) + throw new Exception("Test failed: 4737146 detected"); + } + } else { + throw new Exception("Select failed"); } - } else { - throw new Exception("Select failed"); + } finally { + sc.close(); + selector.close(); } - sc.close(); } public static void main(String[] args) throws Exception {
--- a/test/java/nio/channels/SocketChannel/LocalAddress.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/LocalAddress.java Tue Jul 20 22:21:31 2010 -0700 @@ -38,25 +38,33 @@ static void test1() throws Exception { InetAddress bogus = InetAddress.getByName("0.0.0.0"); - SocketChannel sc = SocketChannel.open(); InetSocketAddress saddr = new InetSocketAddress( InetAddress.getByName(TestUtil.HOST), 23); //Test1: connect only - sc.connect(saddr); - InetAddress isa = sc.socket().getLocalAddress(); - if (isa == null || isa.equals(bogus)) - throw new RuntimeException("test failed"); + SocketChannel sc = SocketChannel.open(); + try { + sc.connect(saddr); + InetAddress ia = sc.socket().getLocalAddress(); + if (ia == null || ia.equals(bogus)) + throw new RuntimeException("test failed"); + } finally { + sc.close(); + } //Test2: bind and connect sc = SocketChannel.open(); - sc.socket().bind(new InetSocketAddress(0)); - if (sc.socket().getLocalPort() == 0) - throw new RuntimeException("test failed"); - sc.socket().connect(saddr); - isa = sc.socket().getLocalAddress(); - if (isa == null || isa.isAnyLocalAddress()) - throw new RuntimeException("test failed"); + try { + sc.socket().bind(new InetSocketAddress(0)); + if (sc.socket().getLocalPort() == 0) + throw new RuntimeException("test failed"); + sc.socket().connect(saddr); + InetAddress ia = sc.socket().getLocalAddress(); + if (ia == null || ia.isAnyLocalAddress()) + throw new RuntimeException("test failed"); + } finally { + sc.close(); + } } }
--- a/test/java/nio/channels/SocketChannel/SocketInheritance.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/SocketInheritance.java Tue Jul 20 22:21:31 2010 -0700 @@ -105,7 +105,11 @@ // launch the child String cmd = System.getProperty("java.home") + File.separator + "bin" + - File.separator + "java SocketInheritance -child " + port; + File.separator + "java"; + String testClasses = System.getProperty("test.classes"); + if (testClasses != null) + cmd += " -cp " + testClasses; + cmd += " SocketInheritance -child " + port; Process p = Runtime.getRuntime().exec(cmd);
--- a/test/java/nio/channels/SocketChannel/Trivial.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/Trivial.java Tue Jul 20 22:21:31 2010 -0700 @@ -33,22 +33,27 @@ public static void main(String[] args) throws Exception { SocketChannel sc = SocketChannel.open(); Selector sel = Selector.open(); - if (sc.keyFor(sel) != null) - throw new Exception("keyFor != null"); - sc.configureBlocking(false); - SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args); - if (sc.keyFor(sel) != sk) - throw new Exception("keyFor returned " + sc.keyFor(sel)); - if (sk.attachment() != args) - throw new Exception("attachment() returned " + sk.attachment()); - Trivial t = new Trivial(); - sk.attach(t); - if (sk.attachment() != t) - throw new Exception("Wrong attachment"); - sk.isReadable(); - sk.isWritable(); - sk.isConnectable(); - sk.isAcceptable(); + try { + if (sc.keyFor(sel) != null) + throw new Exception("keyFor != null"); + sc.configureBlocking(false); + SelectionKey sk = sc.register(sel, SelectionKey.OP_READ, args); + if (sc.keyFor(sel) != sk) + throw new Exception("keyFor returned " + sc.keyFor(sel)); + if (sk.attachment() != args) + throw new Exception("attachment() returned " + sk.attachment()); + Trivial t = new Trivial(); + sk.attach(t); + if (sk.attachment() != t) + throw new Exception("Wrong attachment"); + sk.isReadable(); + sk.isWritable(); + sk.isConnectable(); + sk.isAcceptable(); + } finally { + sel.close(); + sc.close(); + } } }
--- a/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Tue Jul 20 22:21:31 2010 -0700 @@ -57,39 +57,47 @@ System.out.println("\n-- SocketChannel --"); SocketChannel sc = SocketChannel.open(); + try { + check("getLocalPort()", sc.socket().getLocalPort(), -1); + checkIsAnyLocalAddress("getLocalAddress()", + sc.socket().getLocalAddress()); + check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null); - check("getLocalPort()", sc.socket().getLocalPort(), -1); - checkIsAnyLocalAddress("getLocalAddress()", - sc.socket().getLocalAddress()); - check("getLocalSocketAddress()", sc.socket().getLocalSocketAddress(), null); - - check("getPort()", sc.socket().getPort(), 0); - check("getInetAddress()", sc.socket().getInetAddress(), null); - check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null); - + check("getPort()", sc.socket().getPort(), 0); + check("getInetAddress()", sc.socket().getInetAddress(), null); + check("getRemoteSocketAddress()", sc.socket().getRemoteSocketAddress(), null); + } finally { + sc.close(); + } System.out.println("\n-- ServerSocketChannel --"); ServerSocketChannel ssc = ServerSocketChannel.open(); - - check("getLocalPort()", ssc.socket().getLocalPort(), -1); - check("getInetAddress()", ssc.socket().getInetAddress(), null); - check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null); + try { + check("getLocalPort()", ssc.socket().getLocalPort(), -1); + check("getInetAddress()", ssc.socket().getInetAddress(), null); + check("getLocalSocketAddress()", ssc.socket().getLocalSocketAddress(), null); + } finally { + ssc.close(); + } System.out.println("\n-- DatagramChannel --"); DatagramChannel dc = DatagramChannel.open(); - - // not specified - check("getLocalPort()", dc.socket().getLocalPort(), 0); + try { + // not specified + check("getLocalPort()", dc.socket().getLocalPort(), 0); - checkIsAnyLocalAddress("getLocalAddress()", - dc.socket().getLocalAddress()); - check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null); + checkIsAnyLocalAddress("getLocalAddress()", + dc.socket().getLocalAddress()); + check("getLocalSocketAddress()", dc.socket().getLocalSocketAddress(), null); - check("getPort()", dc.socket().getPort(), -1); - check("getInetAddress()", dc.socket().getInetAddress(), null); - check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null); + check("getPort()", dc.socket().getPort(), -1); + check("getInetAddress()", dc.socket().getInetAddress(), null); + check("getRemoteSocketAddress()", dc.socket().getRemoteSocketAddress(), null); + } finally { + dc.close(); + } if (failures > 0) { throw new RuntimeException(failures + " sub-tests(s) failed.");
--- a/test/java/nio/channels/etc/Shadow.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/etc/Shadow.java Tue Jul 20 22:21:31 2010 -0700 @@ -35,7 +35,6 @@ public class Shadow { - private static final int PORT = 2019; static PrintStream log = System.err; private static void dump(ServerSocket s) { @@ -69,7 +68,7 @@ public static void main(String[] args) throws Exception { boolean useChannels = ((args.length == 0) || Boolean.valueOf(args[0]).booleanValue()); - int port = (args.length > 1 ? Integer.parseInt(args[1]) : PORT); + int port = (args.length > 1 ? Integer.parseInt(args[1]) : -1); // open server socket ServerSocket serverSocket; @@ -86,7 +85,8 @@ } // bind server socket to port - SocketAddress bindAddr = new InetSocketAddress(port); + SocketAddress bindAddr = + new InetSocketAddress((port == -1) ? 0 : port); serverSocket.bind(bindAddr); log.println("bound ServerSocket: " + serverSocket);
--- a/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Tue Jul 20 22:21:31 2010 -0700 @@ -26,6 +26,8 @@ * @bug 4997227 * @summary Calling inheritedChannel() after FileDescriptor.in was closed * caused an InternalError to be thrown. + * @build ClosedStreams + * @run main/othervm ClosedStreams */ import java.io.FileDescriptor;
--- a/test/java/nio/charset/coders/BashStreams.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/charset/coders/BashStreams.java Tue Jul 20 22:21:31 2010 -0700 @@ -46,7 +46,7 @@ CharacterGenerator(long seed, String csn, int limit) { rand = new Random(seed); - this.max = Surrogate.UCS4_MAX + 1; + this.max = Character.MAX_CODE_POINT + 1; this.limit = limit; } @@ -77,17 +77,20 @@ int c; for (;;) { c = rand.nextInt(max); - if (Surrogate.is(c) || (c == 0xfffe) || (c == 0xffff)) + if ((Character.isBmpCodePoint(c) + && (Character.isSurrogate((char) c) + || (c == 0xfffe) || (c == 0xffff)))) continue; - if (Surrogate.neededFor(c) && (count == limit - 1)) + if (Character.isSupplementaryCodePoint(c) + && (count == limit - 1)) continue; break; } count++; - if (Surrogate.neededFor(c)) { + if (Character.isSupplementaryCodePoint(c)) { count++; - push(Surrogate.low(c)); - return Surrogate.high(c); + push(Character.lowSurrogate(c)); + return Character.highSurrogate(c); } return (char)c; } @@ -137,7 +140,7 @@ char d = cg.next(); if (c != d) { if (c == '?') { - if (Surrogate.isHigh(d)) + if (Character.isHighSurrogate(d)) cg.next(); continue; } @@ -187,7 +190,7 @@ w.write(ca, 0, n); count += n; } - if (Surrogate.isHigh(ca[n - 1])) + if (Character.isHighSurrogate(ca[n - 1])) w.write(cg.next()); w.close(); } @@ -253,7 +256,8 @@ if (!cg.hasNext()) break; char c = cg.next(); - if (Surrogate.isHigh(c) && (cb.remaining() == 1)) { + if (Character.isHighSurrogate(c) + && cb.remaining() == 1) { cg.push(c); break; } @@ -311,7 +315,7 @@ mismatchedEOF(csn, count + i, cg.count()); char d = cg.next(); if (c == '?') { - if (Surrogate.isHigh(d)) { + if (Character.isHighSurrogate(d)) { cg.next(); continue; }
--- a/test/java/nio/charset/coders/Surrogate.java Thu Jul 15 20:11:45 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -public class Surrogate { - - public static final int UCS4_SURROGATE_MIN = 0x10000; - public static final int UCS4_MAX = (1 << 20) + UCS4_SURROGATE_MIN - 1; - - // UTF-16 surrogate-character ranges - // - public static final char MIN_HIGH = '\uD800'; - public static final char MAX_HIGH = '\uDBFF'; - public static final char MIN_LOW = '\uDC00'; - public static final char MAX_LOW = '\uDFFF'; - public static final char MIN = MIN_HIGH; - public static final char MAX = MAX_LOW; - - public static boolean neededFor(int uc) { - return (uc >= UCS4_SURROGATE_MIN) && (uc <= UCS4_MAX); - } - - public static boolean isHigh(int c) { - return (MIN_HIGH <= c) && (c <= MAX_HIGH); - } - - static char high(int uc) { - return (char)(0xd800 | (((uc - UCS4_SURROGATE_MIN) >> 10) & 0x3ff)); - } - - public static boolean isLow(int c) { - return (MIN_LOW <= c) && (c <= MAX_LOW); - } - - static char low(int uc) { - return (char)(0xdc00 | ((uc - UCS4_SURROGATE_MIN) & 0x3ff)); - } - - public static boolean is(int c) { - return (MIN <= c) && (c <= MAX); - } - - static int toUCS4(char c, char d) { - return (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000; - } - -}
--- a/test/java/nio/charset/coders/Surrogates.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/nio/charset/coders/Surrogates.java Tue Jul 20 22:21:31 2010 -0700 @@ -42,9 +42,8 @@ static void initData() throws IOException { StringBuffer sb = new StringBuffer(); for (int i = 0; i < LEN; i++) { - int c = Surrogate.UCS4_SURROGATE_MIN + 1; - sb.append(Surrogate.high(c)); - sb.append(Surrogate.low(c)); + int c = Character.MIN_SUPPLEMENTARY_CODE_POINT + 1; + sb.append(Character.toChars(c)); } input = sb.toString().toCharArray(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
--- a/test/java/util/Arrays/Sorting.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/java/util/Arrays/Sorting.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,10 +43,11 @@ // Array lengths used in a long run (default) private static final int[] LONG_RUN_LENGTHS = { - 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000}; + 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000 }; // Array lengths used in a short run - private static final int[] SHORT_RUN_LENGTHS = { 1, 2, 3, 21, 55, 1000, 10000 }; + private static final int[] SHORT_RUN_LENGTHS = { + 1, 2, 3, 21, 55, 1000, 10000 }; // Random initial values used in a long run (default) private static final long[] LONG_RUN_RANDOMS = {666, 0xC0FFEE, 999}; @@ -65,99 +66,338 @@ } long end = System.currentTimeMillis(); - out.format("PASS in %d sec.\n", Math.round((end - start) / 1E3)); + out.format("\nPASSED in %d sec.\n", Math.round((end - start) / 1E3)); } private static void testAndCheck(int[] lengths, long[] randoms) { + testEmptyAndNullIntArray(); + testEmptyAndNullLongArray(); + testEmptyAndNullShortArray(); + testEmptyAndNullCharArray(); + testEmptyAndNullByteArray(); + testEmptyAndNullFloatArray(); + testEmptyAndNullDoubleArray(); + for (long random : randoms) { reset(random); - for (int len : lengths) { - testAndCheckWithCheckSum(len, random); - } - reset(random); - - for (int len : lengths) { - testAndCheckWithScrambling(len, random); + for (int length : lengths) { + testAndCheckWithCheckSum(length, random); } reset(random); - for (int len : lengths) { - testAndCheckFloat(len, random); + for (int length : lengths) { + testAndCheckWithScrambling(length, random); + } + reset(random); + + for (int length : lengths) { + testAndCheckFloat(length, random); } reset(random); - for (int len : lengths) { - testAndCheckDouble(len, random); + for (int length : lengths) { + testAndCheckDouble(length, random); } reset(random); - for (int len : lengths) { - testAndCheckRange(len, random); + for (int length : lengths) { + testAndCheckRange(length, random); } reset(random); - for (int len : lengths) { - testAndCheckSubArray(len, random); + for (int length : lengths) { + testAndCheckSubArray(length, random); + } + reset(random); + + for (int length : lengths) { + testStable(length, random); } } } - private static void testAndCheckSubArray(int len, long random) { - int[] golden = new int[len]; + private static void testEmptyAndNullIntArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new int[] {}); + Arrays.sort(new int[] {}, 0, 0); + + try { + Arrays.sort((int[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((int[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(int[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(int[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullLongArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new long[] {}); + Arrays.sort(new long[] {}, 0, 0); + + try { + Arrays.sort((long[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((long[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(long[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(long[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullShortArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new short[] {}); + Arrays.sort(new short[] {}, 0, 0); + + try { + Arrays.sort((short[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((short[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(short[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(short[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullCharArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new char[] {}); + Arrays.sort(new char[] {}, 0, 0); - for (int m = 1; m < len / 2; m *= 2) { + try { + Arrays.sort((char[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((char[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(char[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(char[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullByteArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new byte[] {}); + Arrays.sort(new byte[] {}, 0, 0); + + try { + Arrays.sort((byte[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((byte[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(byte[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(byte[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullFloatArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new float[] {}); + Arrays.sort(new float[] {}, 0, 0); + + try { + Arrays.sort((float[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((float[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(float[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(float[]) shouldn't catch null array"); + } + + private static void testEmptyAndNullDoubleArray() { + ourDescription = "Check empty and null array"; + Arrays.sort(new double[] {}); + Arrays.sort(new double[] {}, 0, 0); + + try { + Arrays.sort((double[]) null); + } catch (NullPointerException expected) { + try { + Arrays.sort((double[]) null, 0, 0); + } catch (NullPointerException expected2) { + return; + } + failed("Arrays.sort(double[],fromIndex,toIndex) shouldn't " + + "catch null array"); + } + failed("Arrays.sort(double[]) shouldn't catch null array"); + } + + private static void testAndCheckSubArray(int length, long random) { + ourDescription = "Check sorting of subarray"; + int[] golden = new int[length]; + boolean newLine = false; + + for (int m = 1; m < length / 2; m *= 2) { + newLine = true; int fromIndex = m; - int toIndex = len - m; + int toIndex = length - m; prepareSubArray(golden, fromIndex, toIndex, m); int[] test = golden.clone(); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test #6: " + converter + - " len = " + len + ", m = " + m); + out.println("Test 'subarray': " + converter + + " length = " + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest = converter.convert(test); - - // outArr(test); + // outArray(test); sortSubArray(convertedTest, fromIndex, toIndex); - // outArr(test); + // outArray(test); checkSubArray(convertedTest, fromIndex, toIndex, m); } } + if (newLine) { + out.println(); + } + } + + private static void testAndCheckRange(int length, long random) { + ourDescription = "Check range check"; + int[] golden = new int[length]; + + for (int m = 1; m < 2 * length; m *= 2) { + for (int i = 1; i <= length; i++) { + golden[i - 1] = i % m + m % i; + } + for (TypeConverter converter : TypeConverter.values()) { + out.println("Test 'range': " + converter + + ", length = " + length + ", m = " + m); + Object convertedGolden = converter.convert(golden); + checkRange(convertedGolden, m); + } + } out.println(); } - private static void testAndCheckRange(int len, long random) { - int[] golden = new int[len]; + private static void testStable(int length, long random) { + ourDescription = "Check if sorting is stable"; + Pair[] a = build(length); - for (int m = 1; m < 2 * len; m *= 2) { - for (int i = 1; i <= len; i++) { - golden[i - 1] = i % m + m % i; + out.println("Test 'stable': " + "random = " + random + + ", length = " + length); + Arrays.sort(a); + checkSorted(a); + checkStable(a); + } + + private static void checkSorted(Pair[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i].getKey() > a[i + 1].getKey()) { + failed(i, "" + a[i].getKey(), "" + a[i + 1].getKey()); } - for (TypeConverter converter : TypeConverter.values()) { - out.println("Test #5: " + converter + - ", len = " + len + ", m = " + m); - Object convertedGolden = converter.convert(golden); - sortRange(convertedGolden, m); - sortEmpty(convertedGolden); + } + } + + private static void checkStable(Pair[] a) { + for (int i = 0; i < a.length / 4; ) { + int key1 = a[i].getKey(); + int value1 = a[i++].getValue(); + int key2 = a[i].getKey(); + int value2 = a[i++].getValue(); + int key3 = a[i].getKey(); + int value3 = a[i++].getValue(); + int key4 = a[i].getKey(); + int value4 = a[i++].getValue(); + + if (!(key1 == key2 && key2 == key3 && key3 == key4)) { + failed("On position " + i + " must keys are different " + + key1 + ", " + key2 + ", " + key3 + ", " + key4); + } + if (!(value1 < value2 && value2 < value3 && value3 < value4)) { + failed("Sorting is not stable at position " + i + + ". Second values have been changed: " + value1 + ", " + + value2 + ", " + value3 + ", " + value4); } } - out.println(); + } + + private static Pair[] build(int length) { + Pair[] a = new Pair[length * 4]; + + for (int i = 0; i < a.length; ) { + int key = ourRandom.nextInt(); + a[i++] = new Pair(key, 1); + a[i++] = new Pair(key, 2); + a[i++] = new Pair(key, 3); + a[i++] = new Pair(key, 4); + } + return a; } - private static void testAndCheckWithCheckSum(int len, long random) { - int[] golden = new int[len]; + private static final class Pair implements Comparable<Pair> { + Pair(int key, int value) { + myKey = key; + myValue = value; + } + + int getKey() { + return myKey; + } + + int getValue() { + return myValue; + } - for (int m = 1; m < 2 * len; m *= 2) { + public int compareTo(Pair pair) { + if (myKey < pair.myKey) { + return -1; + } + if (myKey > pair.myKey) { + return 1; + } + return 0; + } + + @Override + public String toString() { + return "(" + myKey + ", " + myValue + ")"; + } + + private int myKey; + private int myValue; + } + + private static void testAndCheckWithCheckSum(int length, long random) { + ourDescription = "Check sorting with check sum"; + int[] golden = new int[length]; + + for (int m = 1; m < 2 * length; m *= 2) { for (UnsortedBuilder builder : UnsortedBuilder.values()) { builder.build(golden, m); int[] test = golden.clone(); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test #1: " + converter + " " + builder + - "random = " + random + ", len = " + len + - ", m = " + m); + out.println("Test 'check sum': " + converter + " " + + builder + "random = " + random + ", length = " + + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest = converter.convert(test); sort(convertedTest); @@ -168,11 +408,12 @@ out.println(); } - private static void testAndCheckWithScrambling(int len, long random) { - int[] golden = new int[len]; + private static void testAndCheckWithScrambling(int length, long random) { + ourDescription = "Check sorting with scrambling"; + int[] golden = new int[length]; for (int m = 1; m <= 7; m++) { - if (m > len) { + if (m > length) { break; } for (SortedBuilder builder : SortedBuilder.values()) { @@ -181,9 +422,9 @@ scramble(test); for (TypeConverter converter : TypeConverter.values()) { - out.println("Test #2: " + converter + " " + builder + - "random = " + random + ", len = " + len + - ", m = " + m); + out.println("Test 'scrambling': " + converter + " " + + builder + "random = " + random + ", length = " + + length + ", m = " + m); Object convertedGolden = converter.convert(golden); Object convertedTest = converter.convert(test); sort(convertedTest); @@ -194,8 +435,9 @@ out.println(); } - private static void testAndCheckFloat(int len, long random) { - float[] golden = new float[len]; + private static void testAndCheckFloat(int length, long random) { + ourDescription = "Check float sorting"; + float[] golden = new float[length]; final int MAX = 10; boolean newLine = false; @@ -204,22 +446,23 @@ for (int z = 0; z <= MAX; z++) { for (int n = 0; n <= MAX; n++) { for (int p = 0; p <= MAX; p++) { - if (a + g + z + n + p > len) { + if (a + g + z + n + p > length) { continue; } - if (a + g + z + n + p < len) { + if (a + g + z + n + p < length) { continue; } for (FloatBuilder builder : FloatBuilder.values()) { - out.println("Test #3: random = " + random + - ", len = " + len + ", a = " + a + ", g = " + g + - ", z = " + z + ", n = " + n + ", p = " + p); + out.println("Test 'float': random = " + random + + ", length = " + length + ", a = " + a + + ", g = " + g + ", z = " + z + ", n = " + n + + ", p = " + p); builder.build(golden, a, g, z, n, p); float[] test = golden.clone(); scramble(test); - // outArr(test); + // outArray(test); sort(test); - // outArr(test); + // outArray(test); compare(test, golden, a, n, g); } newLine = true; @@ -233,8 +476,9 @@ } } - private static void testAndCheckDouble(int len, long random) { - double[] golden = new double[len]; + private static void testAndCheckDouble(int length, long random) { + ourDescription = "Check double sorting"; + double[] golden = new double[length]; final int MAX = 10; boolean newLine = false; @@ -243,22 +487,22 @@ for (int z = 0; z <= MAX; z++) { for (int n = 0; n <= MAX; n++) { for (int p = 0; p <= MAX; p++) { - if (a + g + z + n + p > len) { + if (a + g + z + n + p > length) { continue; } - if (a + g + z + n + p < len) { + if (a + g + z + n + p < length) { continue; } for (DoubleBuilder builder : DoubleBuilder.values()) { - out.println("Test #4: random = " + random + - ", len = " + len + ", a = " + a + ", g = " + g + - ", z = " + z + ", n = " + n + ", p = " + p); + out.println("Test 'double': random = " + random + + ", length = " + length + ", a = " + a + ", g = " + + g + ", z = " + z + ", n = " + n + ", p = " + p); builder.build(golden, a, g, z, n, p); double[] test = golden.clone(); scramble(test); - // outArr(test); + // outArray(test); sort(test); - // outArr(test); + // outArray(test); compare(test, golden, a, n, g); } newLine = true; @@ -276,37 +520,29 @@ for (int i = 0; i < fromIndex; i++) { a[i] = 0xBABA; } - for (int i = fromIndex; i < toIndex; i++) { a[i] = -i + m; } - for (int i = toIndex; i < a.length; i++) { a[i] = 0xDEDA; } } private static void scramble(int[] a) { - int length = a.length; - - for (int i = 0; i < length * 7; i++) { - swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length)); + for (int i = 0; i < a.length * 7; i++) { + swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); } } private static void scramble(float[] a) { - int length = a.length; - - for (int i = 0; i < length * 7; i++) { - swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length)); + for (int i = 0; i < a.length * 7; i++) { + swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); } } private static void scramble(double[] a) { - int length = a.length; - - for (int i = 0; i < length * 7; i++) { - swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length)); + for (int i = 0; i < a.length * 7; i++) { + swap(a, ourRandom.nextInt(a.length), ourRandom.nextInt(a.length)); } } @@ -393,6 +629,16 @@ } return b; } + }, + INTEGER { + Object convert(int[] a) { + Integer[] b = new Integer[a.length]; + + for (int i = 0; i < a.length; i++) { + b[i] = new Integer(a[i]); + } + return b; + } }; abstract Object convert(int[] a); @@ -691,6 +937,8 @@ compare((float[]) test, (float[]) golden); } else if (test instanceof double[]) { compare((double[]) test, (double[]) golden); + } else if (test instanceof Integer[]) { + compare((Integer[]) test, (Integer[]) golden); } else { failed("Unknow type of array: " + test + " of class " + test.getClass().getName()); @@ -703,13 +951,13 @@ } private static void failed(String message) { - err.format("\n*** FAILED: %s\n\n", message); + err.format("\n*** TEST FAILED - %s\n\n%s\n\n", ourDescription, message); throw new RuntimeException("Test failed - see log file for details"); } private static void failed(int index, String value1, String value2) { - failed("Array is not sorted at " + index + "-th position: " + value1 + - " and " + value2); + failed("Array is not sorted at " + index + "-th position: " + + value1 + " and " + value2); } private static void checkSorted(Object object) { @@ -727,12 +975,22 @@ checkSorted((float[]) object); } else if (object instanceof double[]) { checkSorted((double[]) object); + } else if (object instanceof Integer[]) { + checkSorted((Integer[]) object); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); } } + private static void compare(Integer[] a, Integer[] b) { + for (int i = 0; i < a.length; i++) { + if (a[i].intValue() != b[i].intValue()) { + failed(i, "" + a[i], "" + b[i]); + } + } + } + private static void compare(int[] a, int[] b) { for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) { @@ -789,6 +1047,14 @@ } } + private static void checkSorted(Integer[] a) { + for (int i = 0; i < a.length - 1; i++) { + if (a[i].intValue() > a[i + 1].intValue()) { + failed(i, "" + a[i], "" + a[i + 1]); + } + } + } + private static void checkSorted(int[] a) { for (int i = 0; i < a.length - 1; i++) { if (a[i] > a[i + 1]) { @@ -847,7 +1113,7 @@ private static void checkCheckSum(Object test, Object golden) { if (checkSum(test) != checkSum(golden)) { - failed("Original and sorted arrays seems not identical"); + failed("It seems that original and sorted arrays are not identical"); } } @@ -866,6 +1132,8 @@ return checkSum((float[]) object); } else if (object instanceof double[]) { return checkSum((double[]) object); + } else if (object instanceof Integer[]) { + return checkSum((Integer[]) object); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); @@ -873,6 +1141,15 @@ } } + private static int checkSum(Integer[] a) { + int checkXorSum = 0; + + for (Integer e : a) { + checkXorSum ^= e.intValue(); + } + return checkXorSum; + } + private static int checkSum(int[] a) { int checkXorSum = 0; @@ -951,6 +1228,8 @@ Arrays.sort((float[]) object); } else if (object instanceof double[]) { Arrays.sort((double[]) object); + } else if (object instanceof Integer[]) { + Arrays.sort((Integer[]) object); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); @@ -972,6 +1251,8 @@ Arrays.sort((float[]) object, fromIndex, toIndex); } else if (object instanceof double[]) { Arrays.sort((double[]) object, fromIndex, toIndex); + } else if (object instanceof Integer[]) { + Arrays.sort((Integer[]) object, fromIndex, toIndex); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); @@ -993,12 +1274,36 @@ checkSubArray((float[]) object, fromIndex, toIndex, m); } else if (object instanceof double[]) { checkSubArray((double[]) object, fromIndex, toIndex, m); + } else if (object instanceof Integer[]) { + checkSubArray((Integer[]) object, fromIndex, toIndex, m); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); } } + private static void checkSubArray(Integer[] a, int fromIndex, int toIndex, int m) { + for (int i = 0; i < fromIndex; i++) { + if (a[i].intValue() != 0xBABA) { + failed("Range sort changes left element on position " + i + + ": " + a[i] + ", must be " + 0xBABA); + } + } + + for (int i = fromIndex; i < toIndex - 1; i++) { + if (a[i].intValue() > a[i + 1].intValue()) { + failed(i, "" + a[i], "" + a[i + 1]); + } + } + + for (int i = toIndex; i < a.length; i++) { + if (a[i].intValue() != 0xDEDA) { + failed("Range sort changes right element on position " + i + + ": " + a[i] + ", must be " + 0xDEDA); + } + } + } + private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) { for (int i = 0; i < fromIndex; i++) { if (a[i] != 0xBABA) { @@ -1153,49 +1458,30 @@ } } - private static void sortRange(Object object, int m) { + private static void checkRange(Object object, int m) { if (object instanceof int[]) { - sortRange((int[]) object, m); + checkRange((int[]) object, m); } else if (object instanceof long[]) { - sortRange((long[]) object, m); + checkRange((long[]) object, m); } else if (object instanceof short[]) { - sortRange((short[]) object, m); + checkRange((short[]) object, m); } else if (object instanceof byte[]) { - sortRange((byte[]) object, m); + checkRange((byte[]) object, m); } else if (object instanceof char[]) { - sortRange((char[]) object, m); + checkRange((char[]) object, m); } else if (object instanceof float[]) { - sortRange((float[]) object, m); + checkRange((float[]) object, m); } else if (object instanceof double[]) { - sortRange((double[]) object, m); + checkRange((double[]) object, m); + } else if (object instanceof Integer[]) { + checkRange((Integer[]) object, m); } else { failed("Unknow type of array: " + object + " of class " + object.getClass().getName()); } } - private static void sortEmpty(Object object) { - if (object instanceof int[]) { - Arrays.sort(new int [] {}); - } else if (object instanceof long[]) { - Arrays.sort(new long [] {}); - } else if (object instanceof short[]) { - Arrays.sort(new short [] {}); - } else if (object instanceof byte[]) { - Arrays.sort(new byte [] {}); - } else if (object instanceof char[]) { - Arrays.sort(new char [] {}); - } else if (object instanceof float[]) { - Arrays.sort(new float [] {}); - } else if (object instanceof double[]) { - Arrays.sort(new double [] {}); - } else { - failed("Unknow type of array: " + object + " of class " + - object.getClass().getName()); - } - } - - private static void sortRange(int[] a, int m) { + private static void checkRange(Integer[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1224,7 +1510,36 @@ } } - private static void sortRange(long[] a, int m) { + private static void checkRange(int[] a, int m) { + try { + Arrays.sort(a, m + 1, m); + + failed("Sort does not throw IllegalArgumentException " + + " as expected: fromIndex = " + (m + 1) + + " toIndex = " + m); + } + catch (IllegalArgumentException iae) { + try { + Arrays.sort(a, -m, a.length); + + failed("Sort does not throw ArrayIndexOutOfBoundsException " + + " as expected: fromIndex = " + (-m)); + } + catch (ArrayIndexOutOfBoundsException aoe) { + try { + Arrays.sort(a, 0, a.length + m); + + failed("Sort does not throw ArrayIndexOutOfBoundsException " + + " as expected: toIndex = " + (a.length + m)); + } + catch (ArrayIndexOutOfBoundsException aie) { + return; + } + } + } + } + + private static void checkRange(long[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1253,7 +1568,7 @@ } } - private static void sortRange(byte[] a, int m) { + private static void checkRange(byte[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1282,7 +1597,7 @@ } } - private static void sortRange(short[] a, int m) { + private static void checkRange(short[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1311,7 +1626,7 @@ } } - private static void sortRange(char[] a, int m) { + private static void checkRange(char[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1340,7 +1655,7 @@ } } - private static void sortRange(float[] a, int m) { + private static void checkRange(float[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1369,7 +1684,7 @@ } } - private static void sortRange(double[] a, int m) { + private static void checkRange(double[] a, int m) { try { Arrays.sort(a, m + 1, m); @@ -1410,31 +1725,36 @@ ourSecond = 0; } - private static void outArr(int[] a) { + private static void outArray(Object[] a) { + for (int i = 0; i < a.length; i++) { + out.print(a[i] + " "); + } + out.println(); + } + + private static void outArray(int[] a) { for (int i = 0; i < a.length; i++) { out.print(a[i] + " "); } out.println(); - out.println(); } - private static void outArr(float[] a) { + private static void outArray(float[] a) { for (int i = 0; i < a.length; i++) { out.print(a[i] + " "); } out.println(); - out.println(); } - private static void outArr(double[] a) { + private static void outArray(double[] a) { for (int i = 0; i < a.length; i++) { out.print(a[i] + " "); } out.println(); - out.println(); } private static int ourFirst; private static int ourSecond; private static Random ourRandom; + private static String ourDescription; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/AnonLoggerWeakRefLeak.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.logging.*; + +public class AnonLoggerWeakRefLeak { + public static int DEFAULT_LOOP_TIME = 60; // time is in seconds + + public static void main(String[] args) { + int loop_time = 0; + int max_loop_time = DEFAULT_LOOP_TIME; + + if (args.length == 0) { + System.out.println("INFO: using default time of " + + max_loop_time + " seconds."); + } else { + try { + max_loop_time = Integer.parseInt(args[0]); + } catch (NumberFormatException nfe) { + System.err.println("Error: '" + args[0] + + "': is not a valid seconds value."); + System.err.println("Usage: AnonLoggerWeakRefLeak [seconds]"); + System.exit(1); + } + } + + long count = 0; + long now = 0; + long startTime = System.currentTimeMillis(); + + while (now < (startTime + (max_loop_time * 1000))) { + if ((count % 1000) == 0) { + // Print initial call count to let caller know that + // we're up and running and then periodically + System.out.println("INFO: call count = " + count); + } + + for (int i = 0; i < 100; i++) { + // this Logger call is leaking a WeakReference in Logger.kids + java.util.logging.Logger.getAnonymousLogger(); + count++; + } + + try { + // delay for 1/10 of a second to avoid CPU saturation + Thread.sleep(100); + } catch (InterruptedException ie) { + // ignore any exceptions + } + + now = System.currentTimeMillis(); + } + + System.out.println("INFO: final loop count = " + count); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/AnonLoggerWeakRefLeak.sh Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,247 @@ +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 6942989 +# @ignore until 6964018 is fixed +# @summary Check for WeakReference leak in anonymous Logger objects +# @author Daniel D. Daugherty +# +# @run build AnonLoggerWeakRefLeak +# @run shell/timeout=180 AnonLoggerWeakRefLeak.sh + +# The timeout is: 2 minutes for infrastructure and 1 minute for the test +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +JAVA="${TESTJAVA}"/bin/java +JMAP="${TESTJAVA}"/bin/jmap +JPS="${TESTJAVA}"/bin/jps + +set -eu + +TEST_NAME="AnonLoggerWeakRefLeak" +TARGET_CLASS="java\.lang\.ref\.WeakReference" + +is_cygwin=false +is_mks=false +is_windows=false + +case `uname -s` in +CYGWIN*) + is_cygwin=true + is_windows=true + ;; +Windows_*) + is_mks=true + is_windows=true + ;; +*) + ;; +esac + + +# wrapper for grep +# +grep_cmd() { + set +e + if $is_windows; then + # need dos2unix to get rid of CTRL-M chars from java output + dos2unix | grep "$@" + status="$?" + else + grep "$@" + status="$?" + fi + set -e +} + + +# MAIN begins here +# + +seconds= +if [ "$#" -gt 0 ]; then + seconds="$1" +fi + +# see if this version of jmap supports the '-histo:live' option +jmap_option="-histo:live" +set +e +"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1 +grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1 +status="$?" +set -e +if [ "$status" = 0 ]; then + echo "INFO: switching jmap option from '$jmap_option'\c" + jmap_option="-histo" + echo " to '$jmap_option'." +fi + +"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \ + "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 & +test_pid="$!" +echo "INFO: starting $TEST_NAME as pid = $test_pid" + +# wait for test program to get going +count=0 +while [ "$count" -lt 30 ]; do + sleep 2 + grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1 + if [ "$status" = 0 ]; then + break + fi + count=`expr $count + 1` +done + +if [ "$count" -ge 30 ]; then + echo "ERROR: $TEST_NAME failed to get going." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 1 +elif [ "$count" -gt 1 ]; then + echo "INFO: $TEST_NAME took $count loops to start." +fi + +if $is_cygwin; then + # We need the Windows pid for jmap and not the Cygwin pid. + # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris. + jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'` + if [ -z "$jmap_pid" ]; then + echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid" +else + jmap_pid="$test_pid" +fi + +decreasing_cnt=0 +increasing_cnt=0 +loop_cnt=0 +prev_instance_cnt=0 + +while true; do + # Output format for 'jmap -histo' in JDK1.5.0: + # + # <#bytes> <#instances> <class_name> + # + # Output format for 'jmap -histo:live': + # + # <num>: <#instances> <#bytes> <class_name> + # + set +e + "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1 + status="$?" + set -e + + if [ "$status" != 0 ]; then + echo "INFO: jmap exited with exit code = $status" + if [ "$loop_cnt" = 0 ]; then + echo "INFO: on the first iteration so no samples were taken." + echo "INFO: start of jmap output:" + cat "$TEST_NAME.jmap" + echo "INFO: end of jmap output." + echo "FAIL: jmap is unable to take any samples." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + echo "INFO: The likely reason is that $TEST_NAME has finished running." + break + fi + + instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \ + < "$TEST_NAME.jmap" \ + | sed ' + # strip leading whitespace; does nothing in JDK1.5.0 + s/^[ ][ ]*// + # strip <#bytes> in JDK1.5.0; does nothing otherwise + s/^[1-9][0-9]*[ ][ ]*// + # strip <num>: field; does nothing in JDK1.5.0 + s/^[1-9][0-9]*:[ ][ ]*// + # strip <class_name> field + s/[ ].*// + '` + if [ -z "$instance_cnt" ]; then + echo "INFO: instance count is unexpectedly empty" + if [ "$loop_cnt" = 0 ]; then + echo "INFO: on the first iteration so no sample was found." + echo "INFO: There is likely a problem with the sed filter." + echo "INFO: start of jmap output:" + cat "$TEST_NAME.jmap" + echo "INFO: end of jmap output." + echo "FAIL: cannot find the instance count value." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + else + echo "INFO: instance_cnt = $instance_cnt" + + if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then + increasing_cnt=`expr $increasing_cnt + 1` + else + decreasing_cnt=`expr $decreasing_cnt + 1` + fi + prev_instance_cnt="$instance_cnt" + fi + + # delay between samples + sleep 5 + + loop_cnt=`expr $loop_cnt + 1` +done + +echo "INFO: increasing_cnt = $increasing_cnt" +echo "INFO: decreasing_cnt = $decreasing_cnt" + +echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects" +if [ "$decreasing_cnt" = 0 ]; then + echo "INFO: is always increasing." + echo "FAIL: This indicates that there is a memory leak." >&2 + exit 2 +fi + +echo "INFO: is both increasing and decreasing." +echo "PASS: This indicates that there is not a memory leak." +exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/LoggerWeakRefLeak.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.logging.*; + +public class LoggerWeakRefLeak { + // AnonLoggerWeakRefLeak checks for one weak reference leak. + // LoggerWeakRefLeak checks for two weak reference leaks so + // this test runs twice as long, by default. + public static int DEFAULT_LOOP_TIME = 120; // time is in seconds + + public static void main(String[] args) { + int loop_time = 0; + int max_loop_time = DEFAULT_LOOP_TIME; + + if (args.length == 0) { + System.out.println("INFO: using default time of " + + max_loop_time + " seconds."); + } else { + try { + max_loop_time = Integer.parseInt(args[0]); + } catch (NumberFormatException nfe) { + System.err.println("Error: '" + args[0] + + "': is not a valid seconds value."); + System.err.println("Usage: LoggerWeakRefLeak [seconds]"); + System.exit(1); + } + } + + long count = 0; + int loggerCount = 0; + long now = 0; + long startTime = System.currentTimeMillis(); + + while (now < (startTime + (max_loop_time * 1000))) { + if ((count % 1000) == 0) { + // Print initial call count to let caller know that + // we're up and running and then periodically + System.out.println("INFO: call count = " + count); + } + + for (int i = 0; i < 100; i++) { + // This Logger call is leaking two different WeakReferences: + // - one in LogManager.LogNode + // - one in Logger.kids + java.util.logging.Logger.getLogger("logger-" + loggerCount); + count++; + if (++loggerCount >= 25000) { + // Limit the Logger namespace used by the test so + // the weak refs in LogManager.loggers that are + // being properly managed don't skew the counts + // by too much. + loggerCount = 0; + } + } + + try { + // delay for 1/10 of a second to avoid CPU saturation + Thread.sleep(100); + } catch (InterruptedException ie) { + // ignore any exceptions + } + + now = System.currentTimeMillis(); + } + + System.out.println("INFO: final loop count = " + count); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/util/logging/LoggerWeakRefLeak.sh Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,247 @@ +# +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 6942989 +# @ignore until 6964018 is fixed +# @summary Check for WeakReference leak in Logger objects +# @author Daniel D. Daugherty +# +# @run build LoggerWeakRefLeak +# @run shell/timeout=240 LoggerWeakRefLeak.sh + +# The timeout is: 2 minutes for infrastructure and 1 minute for the test +# + +if [ "${TESTJAVA}" = "" ] +then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTSRC}" = "" ] +then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "${TESTCLASSES}" = "" ] +then + echo "TESTCLASSES not set. Test cannot execute. Failed." + exit 1 +fi + +JAVA="${TESTJAVA}"/bin/java +JMAP="${TESTJAVA}"/bin/jmap +JPS="${TESTJAVA}"/bin/jps + +set -eu + +TEST_NAME="LoggerWeakRefLeak" +TARGET_CLASS="java\.lang\.ref\.WeakReference" + +is_cygwin=false +is_mks=false +is_windows=false + +case `uname -s` in +CYGWIN*) + is_cygwin=true + is_windows=true + ;; +Windows_*) + is_mks=true + is_windows=true + ;; +*) + ;; +esac + + +# wrapper for grep +# +grep_cmd() { + set +e + if $is_windows; then + # need dos2unix to get rid of CTRL-M chars from java output + dos2unix | grep "$@" + status="$?" + else + grep "$@" + status="$?" + fi + set -e +} + + +# MAIN begins here +# + +seconds= +if [ "$#" -gt 0 ]; then + seconds="$1" +fi + +# see if this version of jmap supports the '-histo:live' option +jmap_option="-histo:live" +set +e +"${JMAP}" "$jmap_option" 0 > "$TEST_NAME.jmap" 2>&1 +grep '^Usage: ' "$TEST_NAME.jmap" > /dev/null 2>&1 +status="$?" +set -e +if [ "$status" = 0 ]; then + echo "INFO: switching jmap option from '$jmap_option'\c" + jmap_option="-histo" + echo " to '$jmap_option'." +fi + +"${JAVA}" ${TESTVMOPTS} -classpath "${TESTCLASSES}" \ + "$TEST_NAME" $seconds > "$TEST_NAME.log" 2>&1 & +test_pid="$!" +echo "INFO: starting $TEST_NAME as pid = $test_pid" + +# wait for test program to get going +count=0 +while [ "$count" -lt 30 ]; do + sleep 2 + grep_cmd '^INFO: call count = 0$' < "$TEST_NAME.log" > /dev/null 2>&1 + if [ "$status" = 0 ]; then + break + fi + count=`expr $count + 1` +done + +if [ "$count" -ge 30 ]; then + echo "ERROR: $TEST_NAME failed to get going." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 1 +elif [ "$count" -gt 1 ]; then + echo "INFO: $TEST_NAME took $count loops to start." +fi + +if $is_cygwin; then + # We need the Windows pid for jmap and not the Cygwin pid. + # Note: '\t' works on Cygwin, but doesn't seem to work on Solaris. + jmap_pid=`"${JPS}"| grep_cmd "[ \t]$TEST_NAME$" | sed 's/[ \t].*//'` + if [ -z "$jmap_pid" ]; then + echo "FAIL: jps could not map Cygwin pid to Windows pid." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + echo "INFO: pid = $test_pid maps to Windows pid = $jmap_pid" +else + jmap_pid="$test_pid" +fi + +decreasing_cnt=0 +increasing_cnt=0 +loop_cnt=0 +prev_instance_cnt=0 + +while true; do + # Output format for 'jmap -histo' in JDK1.5.0: + # + # <#bytes> <#instances> <class_name> + # + # Output format for 'jmap -histo:live': + # + # <num>: <#instances> <#bytes> <class_name> + # + set +e + "${JMAP}" "$jmap_option" "$jmap_pid" > "$TEST_NAME.jmap" 2>&1 + status="$?" + set -e + + if [ "$status" != 0 ]; then + echo "INFO: jmap exited with exit code = $status" + if [ "$loop_cnt" = 0 ]; then + echo "INFO: on the first iteration so no samples were taken." + echo "INFO: start of jmap output:" + cat "$TEST_NAME.jmap" + echo "INFO: end of jmap output." + echo "FAIL: jmap is unable to take any samples." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + echo "INFO: The likely reason is that $TEST_NAME has finished running." + break + fi + + instance_cnt=`grep_cmd "[ ]$TARGET_CLASS$" \ + < "$TEST_NAME.jmap" \ + | sed ' + # strip leading whitespace; does nothing in JDK1.5.0 + s/^[ ][ ]*// + # strip <#bytes> in JDK1.5.0; does nothing otherwise + s/^[1-9][0-9]*[ ][ ]*// + # strip <num>: field; does nothing in JDK1.5.0 + s/^[1-9][0-9]*:[ ][ ]*// + # strip <class_name> field + s/[ ].*// + '` + if [ -z "$instance_cnt" ]; then + echo "INFO: instance count is unexpectedly empty" + if [ "$loop_cnt" = 0 ]; then + echo "INFO: on the first iteration so no sample was found." + echo "INFO: There is likely a problem with the sed filter." + echo "INFO: start of jmap output:" + cat "$TEST_NAME.jmap" + echo "INFO: end of jmap output." + echo "FAIL: cannot find the instance count value." >&2 + echo "INFO: killing $test_pid" + kill "$test_pid" + exit 2 + fi + else + echo "INFO: instance_cnt = $instance_cnt" + + if [ "$instance_cnt" -gt "$prev_instance_cnt" ]; then + increasing_cnt=`expr $increasing_cnt + 1` + else + decreasing_cnt=`expr $decreasing_cnt + 1` + fi + prev_instance_cnt="$instance_cnt" + fi + + # delay between samples + sleep 5 + + loop_cnt=`expr $loop_cnt + 1` +done + +echo "INFO: increasing_cnt = $increasing_cnt" +echo "INFO: decreasing_cnt = $decreasing_cnt" + +echo "INFO: The instance count of" `eval echo $TARGET_CLASS` "objects" +if [ "$decreasing_cnt" = 0 ]; then + echo "INFO: is always increasing." + echo "FAIL: This indicates that there is a memory leak." >&2 + exit 2 +fi + +echo "INFO: is both increasing and decreasing." +echo "PASS: This indicates that there is not a memory leak." +exit 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/AbstractButton/6711682/bug6711682.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6711682 + @summary JCheckBox in JTable: checkbox doesn't alaways respond to the first mouse click + @author Alexander Potochkin + @run main bug6711682 +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.awt.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.util.EventObject; + +public class bug6711682 { + private static JCheckBox editorCb; + private static JCheckBox rendererCb; + private static JTable table; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(50); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + toolkit.realSync(); + Point l = table.getLocationOnScreen(); + int h = table.getRowHeight(); + for (int i = 0; i < 3; i++) { + robot.mouseMove(l.x + 5, l.y + 5 + i * h); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + // Without pressing F2 the last table's cell + // reported <code>false</code> value + // note that I can't press it inside the for loop + // because it doesn't reproduce the bug + robot.keyPress(KeyEvent.VK_F2); + robot.keyRelease(KeyEvent.VK_F2); + + for (int i = 0; i < 3; i++) { + if (!Boolean.TRUE.equals(table.getValueAt(i, 0))) { + throw new RuntimeException("Row #" + i + " checkbox is not selected"); + } + } + for (int i = 2; i >= 0; i--) { + robot.mouseMove(l.x + 5, l.y + 5 + i * h); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + robot.keyPress(KeyEvent.VK_F2); + robot.keyRelease(KeyEvent.VK_F2); + for (int i = 0; i < 3; i++) { + if (Boolean.TRUE.equals(table.getValueAt(i, 0))) { + throw new RuntimeException("Row #" + i + " checkbox is selected"); + } + } + } + + private static void createAndShowGUI() { + editorCb = new JCheckBox(); + rendererCb = new JCheckBox(); + JFrame f = new JFrame("Table with CheckBox"); + Container p = f.getContentPane(); + p.setLayout(new BorderLayout()); + table = new JTable(new Object[][]{{false}, {false}, {false}}, new Object[]{"CheckBox"}); + TableCellEditor editor = new TableCellEditor() { + int editedRow; + + public Component getTableCellEditorComponent(JTable table, + Object value, boolean isSelected, int row, int column) { + this.editedRow = row; + editorCb.setSelected(Boolean.TRUE.equals(value)); + editorCb.setBackground(UIManager.getColor("Table.selectionBackground")); + return editorCb; + } + + public void addCellEditorListener(CellEditorListener l) { + } + + public void cancelCellEditing() { + } + + public Object getCellEditorValue() { + return editorCb.isSelected(); + } + + public boolean isCellEditable(EventObject anEvent) { + return true; + } + + public void removeCellEditorListener(CellEditorListener l) { + } + + public boolean shouldSelectCell(EventObject anEvent) { + return true; + } + + public boolean stopCellEditing() { + table.getModel().setValueAt(editorCb.isSelected(), editedRow, 0); + return true; + } + }; + table.getColumnModel().getColumn(0).setCellEditor(editor); + + TableCellRenderer renderer = new TableCellRenderer() { + public Component getTableCellRendererComponent(JTable table, + Object value, boolean isSelected, boolean hasFocus, + int row, int column) { + rendererCb.setSelected(Boolean.TRUE.equals(value)); + return rendererCb; + } + }; + table.getColumnModel().getColumn(0).setCellRenderer(renderer); + + p.add(table, BorderLayout.CENTER); + + f.pack(); + f.setVisible(true); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JFileChooser/6520101/bug6520101.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test @(#)bug6520101 + * @bug 6520101 + * @summary JFileChooser throws OOM in 1.4.2, 5.0u4 and 1.6.0 + * @author Praveen Gupta + * @run main/othervm/timeout=600 -Xmx8m -verify bug6520101 +*/ + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class bug6520101 implements Runnable { + + private static final int ATTEMPTS = 500; + private static final int INTERVAL = 100; + + private static final boolean ALWAYS_NEW_INSTANCE = false; + private static final boolean DO_GC_EACH_INTERVAL = false; + private static final boolean UPDATE_UI_EACH_INTERVAL = true; + private static final boolean AUTO_CLOSE_DIALOG = true; + + private static JFileChooser CHOOSER; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + + for (int i = 0; i < ATTEMPTS; i++) { + doAttempt(); + } + + System.out.println("Test passed successfully"); + } + + private static void doAttempt() throws InterruptedException { + if (ALWAYS_NEW_INSTANCE || (CHOOSER == null)) + CHOOSER = new JFileChooser("."); + + if (UPDATE_UI_EACH_INTERVAL) { + CHOOSER.updateUI(); + } + + if (AUTO_CLOSE_DIALOG) { + Thread t = new Thread(new bug6520101(CHOOSER)); + t.start(); + CHOOSER.showOpenDialog(null); + t.join(); + } else { + CHOOSER.showOpenDialog(null); + } + + if (DO_GC_EACH_INTERVAL) { + System.gc(); + } + } + + private final JFileChooser chooser; + + bug6520101(JFileChooser chooser) { + this.chooser = chooser; + } + + public void run() { + while (!this.chooser.isShowing()) { + try { + Thread.sleep(30); + } catch (InterruptedException exception) { + exception.printStackTrace(); + } + } + + Timer timer = new Timer(INTERVAL, new ActionListener() { + public void actionPerformed(ActionEvent e) { + chooser.cancelSelection(); + } + }); + + timer.setRepeats(false); + timer.start(); + } +}
--- a/test/javax/swing/JInternalFrame/6725409/bug6725409.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/javax/swing/JInternalFrame/6725409/bug6725409.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ new com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel()); } catch(UnsupportedLookAndFeelException e) { System.out.println("The test is for Windows LaF only"); - System.exit(0); + return; } final bug6725409 bug6725409 = new bug6725409();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JPopupMenu/6495920/bug6495920.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6495920 + * @summary Tests that if the JPopupMenu.setVisible method throws an exception, + interaction with GNOME is not crippled + * @author Sergey Malenkov + * @library ../.. + */ + +import sun.awt.AppContext; + +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.lang.reflect.Field; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicPopupMenuUI; + +public class bug6495920 implements Thread.UncaughtExceptionHandler { + + public static void main(String[] args) throws Throwable { + SwingTest.start(bug6495920.class); + } + + private static Robot robot; + private final JPanel panel; + + public bug6495920(JFrame frame) { + JPopupMenu menu = new JPopupMenu() { + public void setVisible(boolean visible) { + super.setVisible(visible); + throw new AssertionError(visible ? "show popup" : "hide popup"); + } + }; + for (int i = 0; i < 10; i++) { + menu.add(new JMenuItem(String.valueOf(i))); + } + this.panel = new JPanel(); + this.panel.setComponentPopupMenu(menu); + frame.add(this.panel); + } + + public void firstShowPopup() throws Exception { + Point point = this.panel.getLocation(); + SwingUtilities.convertPointToScreen(point, this.panel); + + robot = new Robot(); // initialize shared static field first time + robot.mouseMove(point.x + 1, point.y + 1); + robot.mousePress(InputEvent.BUTTON3_MASK); + Thread.currentThread().setUncaughtExceptionHandler(this); + robot.mouseRelease(InputEvent.BUTTON3_MASK); // causes first AssertionError on EDT + } + + public void secondHidePopup() { + Point point = this.panel.getLocation(); + SwingUtilities.convertPointToScreen(point, this.panel); + + robot.mouseMove(point.x - 1, point.y - 1); + Thread.currentThread().setUncaughtExceptionHandler(this); + robot.mousePress(InputEvent.BUTTON1_MASK); // causes second AssertionError on EDT + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + + public void thirdValidate() throws Exception { + Field key = BasicPopupMenuUI.class.getDeclaredField("MOUSE_GRABBER_KEY"); + key.setAccessible(true); + + Object grabber = AppContext.getAppContext().get(key.get(null)); + if (grabber == null) { + throw new Exception("cannot find a mouse grabber in app's context"); + } + + Field field = grabber.getClass().getDeclaredField("grabbedWindow"); + field.setAccessible(true); + + Object window = field.get(grabber); + if (window != null) { + throw new Exception("interaction with GNOME is crippled"); + } + } + + public void uncaughtException(Thread thread, Throwable throwable) { + System.out.println(throwable); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/JTable/6777378/bug6777378.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 6777378 + @summary NullPointerException in XPDefaultRenderer.paint() + @author Alexander Potochkin + @run main bug6777378 +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.JTableHeader; +import javax.swing.plaf.metal.MetalLookAndFeel; +import java.awt.event.MouseEvent; +import java.awt.event.InputEvent; +import java.awt.*; + +public class bug6777378 { + private static JFrame frame; + private static JTableHeader header; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(20); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } catch (Exception e) { + e.printStackTrace(); + } + JTable table = new JTable(new AbstractTableModel() { + public int getRowCount() { + return 10; + } + + public int getColumnCount() { + return 10; + } + + public Object getValueAt(int rowIndex, int columnIndex) { + return "" + rowIndex + " " + columnIndex; + } + }); + + header = new JTableHeader(table.getColumnModel()); + header.setToolTipText("hello"); + + frame = new JFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(header); + + frame.setSize(300, 300); + frame.setVisible(true); + } + }); + toolkit.realSync(); + Point point = header.getLocationOnScreen(); + robot.mouseMove(point.x + 20, point.y + 50); + robot.mouseMove(point.x + 30, point.y + 50); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/border/Test4129681.html Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,10 @@ +<html> +<body> +When applet starts, you'll see a checkbox and a label with a titled border. +Turn on the checkbox to disable the label. +The test passes if the title of the border is disabled as well as the label. + +<applet width="300" height="200" code="Test4129681.class"> +</applet> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/border/Test4129681.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4129681 + * @summary Tests enabling/disabling of titled border's caption + * @author Sergey Malenkov + * @run applet/manual=yesno Test4129681.html + */ + +import java.awt.BorderLayout; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JCheckBox; +import javax.swing.JLabel; + +public class Test4129681 extends JApplet implements ItemListener { + private JLabel label; + + @Override + public void init() { + JCheckBox check = new JCheckBox("disable"); + check.addItemListener(this); + + this.label = new JLabel("message"); + this.label.setBorder(BorderFactory.createTitledBorder("label")); + this.label.setEnabled(!check.isSelected()); + + add(BorderLayout.NORTH, check); + add(BorderLayout.CENTER, this.label); + } + + public void itemStateChanged(ItemEvent event) { + this.label.setEnabled(ItemEvent.DESELECTED == event.getStateChange()); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/border/Test4760089.html Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,10 @@ +<html> +<body> +When applet starts, you'll see a panel with a compound titled border. +If one of its titles is overstriken with the border's line then test fails. +Otherwise test passes. + +<applet width="600" height="300" code="Test4760089.class"> +</applet> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/javax/swing/border/Test4760089.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4760089 + * @summary Tests that titled border do not paint inner titled border over its caption + * @author Sergey Malenkov + * @run applet/manual=yesno Test4760089.html + */ + +import javax.swing.JApplet; +import javax.swing.JPanel; +import javax.swing.border.Border; +import javax.swing.border.EtchedBorder; +import javax.swing.border.TitledBorder; + +public class Test4760089 extends JApplet { + @Override + public void init() { + Border border = new EtchedBorder(); + border = new TitledBorder(border, "LEFT", TitledBorder.LEFT, TitledBorder.TOP); + border = new TitledBorder(border, "RIGHT", TitledBorder.RIGHT, TitledBorder.TOP); + + JPanel panel = new JPanel(); + panel.setBorder(border); + getContentPane().add(panel); + } +}
--- a/test/sun/nio/ch/Basic.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/ch/Basic.java Tue Jul 20 22:21:31 2010 -0700 @@ -32,5 +32,7 @@ public class Basic { public static void main(String[] args) throws Exception { Pipe p = Pipe.open(); + p.source().close(); + p.sink().close(); } }
--- a/test/sun/nio/ch/TempBuffer.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/ch/TempBuffer.java Tue Jul 20 22:21:31 2010 -0700 @@ -54,8 +54,12 @@ blah.deleteOnExit(); TempBuffer.initTestFile(blah); RandomAccessFile raf = new RandomAccessFile(blah, "rw"); - FileChannel fs = raf.getChannel(); - fs.transferTo(0, SIZE, Channels.newChannel(out)); + FileChannel fc = raf.getChannel(); + try { + fc.transferTo(0, SIZE, Channels.newChannel(out)); + } finally { + fc.close(); + } out.flush(); } catch (IOException ioe) { throw new RuntimeException(ioe); @@ -69,10 +73,17 @@ File blah = File.createTempFile("blah2", null); blah.deleteOnExit(); RandomAccessFile raf = new RandomAccessFile(blah, "rw"); - FileChannel fs = raf.getChannel(); - raf.setLength(SIZE); - fs.transferFrom(Channels.newChannel(in), 0, SIZE); - fs.close(); + FileChannel fc = raf.getChannel(); + try { + raf.setLength(SIZE); + fc.transferFrom(Channels.newChannel(in), 0, SIZE); + } finally { + fc.close(); + } + + sourceChannel.close(); + sinkChannel.close(); + blah.delete(); } private static void initTestFile(File blah) throws IOException {
--- a/test/sun/nio/cs/FindDecoderBugs.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/cs/FindDecoderBugs.java Tue Jul 20 22:21:31 2010 -0700 @@ -298,7 +298,7 @@ void testRandomly(byte[] prefix, int n) { int len = prefix.length; byte[] ia = Arrays.copyOf(prefix, len + n); - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 5000; i++) { for (int j = 0; j < n; j++) ia[len + j] = randomByte(); test(ia); @@ -435,6 +435,9 @@ static void equal(Object x, Object y) { if (x == null ? y == null : x.equals(y)) pass(); else fail(x + " not equal to " + y);} + static void equal(int x, int y) { + if (x == y) pass(); + else fail(x + " not equal to " + y);} public static void main(String[] args) throws Throwable { try {realMain(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
--- a/test/sun/nio/cs/ReadZero.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/cs/ReadZero.java Tue Jul 20 22:21:31 2010 -0700 @@ -43,15 +43,18 @@ return 0; } }; - - is.read(new byte[1], 0, 1); // ok - InputStreamReader isr = new InputStreamReader(is); + try { + is.read(new byte[1], 0, 1); // ok + InputStreamReader isr = new InputStreamReader(is); - try { - int res = isr.read(new char[1], 0, 1); - } catch (IOException x) { - System.out.println("IOException caught"); - return; + try { + int res = isr.read(new char[1], 0, 1); + } catch (IOException x) { + System.out.println("IOException caught"); + return; + } + } finally { + is.close(); } throw new RuntimeException("IOException not thrown"); }
--- a/test/sun/nio/cs/Test4206507.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/cs/Test4206507.java Tue Jul 20 22:21:31 2010 -0700 @@ -32,7 +32,12 @@ public class Test4206507 { public static void main(String[] args) throws UnsupportedEncodingException { - Locale.setDefault(new Locale("tr", "TR")); - byte[] b = "".getBytes("ISO8859-9"); + Locale l = Locale.getDefault(); + try { + Locale.setDefault(new Locale("tr", "TR")); + byte[] b = "".getBytes("ISO8859-9"); + } finally { + Locale.setDefault(l); + } } }
--- a/test/sun/nio/cs/TestStringCoding.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/cs/TestStringCoding.java Tue Jul 20 22:21:31 2010 -0700 @@ -26,7 +26,7 @@ /* @test @bug 6636323 6636319 @summary Test if StringCoding and NIO result have the same de/encoding result - * @run main/timeout=2000 TestStringCoding + * @run main/othervm/timeout=2000 TestStringCoding */ import java.util.*;
--- a/test/sun/nio/cs/TestX11CNS.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/nio/cs/TestX11CNS.java Tue Jul 20 22:21:31 2010 -0700 @@ -94,6 +94,8 @@ } static void compare(Charset newCS, Charset oldCS) throws Exception { + if (newCS == null) + return; // does not exist on this platform char[] cc = getChars(newCS, oldCS); System.out.printf(" Diff <%s> <%s>...%n", newCS.name(), oldCS.name()); @@ -120,14 +122,22 @@ } } + private static Charset getCharset(String czName) + throws Exception { + try { + return (Charset)Class.forName(czName).newInstance(); + } catch (ClassNotFoundException e){} + return null; // does not exist + } + public static void main(String[] args) throws Exception { - compare(new sun.awt.motif.X11CNS11643P1(), + compare(getCharset("sun.awt.motif.X11CNS11643P1"), new X11CNS11643P1()); - compare(new sun.awt.motif.X11CNS11643P2(), + compare(getCharset("sun.awt.motif.X11CNS11643P2"), new X11CNS11643P2()); - compare(new sun.awt.motif.X11CNS11643P3(), + compare(getCharset("sun.awt.motif.X11CNS11643P3"), new X11CNS11643P3()); }
--- a/test/sun/security/krb5/auto/SSL.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/security/krb5/auto/SSL.java Tue Jul 20 22:21:31 2010 -0700 @@ -25,6 +25,16 @@ * @test * @bug 6894643 6913636 * @summary Test JSSE Kerberos ciphersuite + * @run main SSL TLS_KRB5_WITH_RC4_128_SHA + * @run main SSL TLS_KRB5_WITH_RC4_128_MD5 + * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_SHA + * @run main SSL TLS_KRB5_WITH_3DES_EDE_CBC_MD5 + * @run main SSL TLS_KRB5_WITH_DES_CBC_SHA + * @run main SSL TLS_KRB5_WITH_DES_CBC_MD5 + * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_SHA + * @run main SSL TLS_KRB5_EXPORT_WITH_RC4_40_MD5 + * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA + * @run main SSL TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 */ import java.io.*; import java.net.InetAddress; @@ -37,7 +47,7 @@ public class SSL { - private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA"; + private static String krb5Cipher; private static final int LOOP_LIMIT = 1; private static int loopCount = 0; private static volatile String server; @@ -45,6 +55,8 @@ public static void main(String[] args) throws Exception { + krb5Cipher = args[0]; + KDC kdc = KDC.create(OneKDC.REALM); // Run this after KDC, so our own DNS service can be started try { @@ -117,7 +129,7 @@ SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(server, port); // Enable only a KRB5 cipher suite. - String enabledSuites[] = {KRB5_CIPHER}; + String enabledSuites[] = {krb5Cipher}; sslSocket.setEnabledCipherSuites(enabledSuites); // Should check for exception if enabledSuites is not supported @@ -155,7 +167,7 @@ port = sslServerSocket.getLocalPort(); // Enable only a KRB5 cipher suite. - String enabledSuites[] = {KRB5_CIPHER}; + String enabledSuites[] = {krb5Cipher}; sslServerSocket.setEnabledCipherSuites(enabledSuites); // Should check for exception if enabledSuites is not supported
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/krb5/etype/ETypeOrder.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * @test + * @bug 6844907 + * @summary krb5 etype order should be from strong to weak + */ + +import sun.security.krb5.internal.crypto.EType; + +public class ETypeOrder { + public static void main(String[] args) throws Exception { + + // File does not exist, so that the system-default one won't be used + System.setProperty("java.security.krb5.conf", "no_such_file"); + int[] etypes = EType.getBuiltInDefaults(); + + // Reference order, note that 2 is not implemented in Java + int correct[] = { 18, 17, 16, 23, 1, 3, 2 }; + + int match = 0; + loopi: for (int i=0; i<etypes.length; i++) { + for (; match < correct.length; match++) { + if (etypes[i] == correct[match]) { + System.out.println("Find " + etypes[i] + " at #" + match); + continue loopi; + } + } + throw new Exception("No match or bad order for " + etypes[i]); + } + } +}
--- a/test/sun/security/krb5/ktab/HighestKvno.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/sun/security/krb5/ktab/HighestKvno.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -227,9 +227,6 @@ if (keys[0].getKeyVersionNumber() != 5) { throw new Exception("Highest not first"); } - if (ktab.readServiceKey(pn).getKeyVersionNumber() != 5) { - throw new Exception("Highest not chosen"); - } new File("kt").delete(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/sun/security/pkcs12/PKCS12SameKeyId.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6958026 + * @summary Problem with PKCS12 keystore + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.AlgorithmParameters; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import sun.security.pkcs.EncryptedPrivateKeyInfo; +import sun.security.tools.KeyTool; +import sun.security.util.ObjectIdentifier; +import sun.security.x509.AlgorithmId; +import sun.security.x509.X500Name; + +public class PKCS12SameKeyId { + + private static final String JKSFILE = "PKCS12SameKeyId.jks"; + private static final String P12FILE = "PKCS12SameKeyId.p12"; + private static final char[] PASSWORD = "changeit".toCharArray(); + private static final int SIZE = 10; + + public static void main(String[] args) throws Exception { + + // Prepare a JKS keystore with many entries + new File(JKSFILE).delete(); + for (int i=0; i<SIZE; i++) { + System.err.print("."); + String cmd = "-keystore " + JKSFILE + + " -storepass changeit -keypass changeit " + + "-genkeypair -alias p" + i + " -dname CN=" + i; + KeyTool.main(cmd.split(" ")); + } + + // Prepare EncryptedPrivateKeyInfo parameters, copied from various + // places in PKCS12KeyStore.java + AlgorithmParameters algParams = + AlgorithmParameters.getInstance("PBEWithSHA1AndDESede"); + algParams.init(new PBEParameterSpec("12345678".getBytes(), 1024)); + AlgorithmId algid = new AlgorithmId( + new ObjectIdentifier("1.2.840.113549.1.12.1.3"), algParams); + + PBEKeySpec keySpec = new PBEKeySpec(PASSWORD); + SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE"); + SecretKey skey = skFac.generateSecret(keySpec); + + Cipher cipher = Cipher.getInstance("PBEWithSHA1AndDESede"); + cipher.init(Cipher.ENCRYPT_MODE, skey, algParams); + + // Pre-calculated keys and certs and aliases + byte[][] keys = new byte[SIZE][]; + Certificate[][] certChains = new Certificate[SIZE][]; + String[] aliases = new String[SIZE]; + + // Reads from JKS keystore and pre-calculate + KeyStore ks = KeyStore.getInstance("jks"); + ks.load(new FileInputStream(JKSFILE), PASSWORD); + for (int i=0; i<SIZE; i++) { + aliases[i] = "p" + i; + byte[] enckey = cipher.doFinal( + ks.getKey(aliases[i], PASSWORD).getEncoded()); + keys[i] = new EncryptedPrivateKeyInfo(algid, enckey).getEncoded(); + certChains[i] = ks.getCertificateChain(aliases[i]); + } + + // Write into PKCS12 keystore. Use this overloaded version of + // setKeyEntry() to be as fast as possible, so that they would + // have same localKeyId. + KeyStore p12 = KeyStore.getInstance("pkcs12"); + p12.load(null, PASSWORD); + for (int i=0; i<SIZE; i++) { + p12.setKeyEntry(aliases[i], keys[i], certChains[i]); + } + p12.store(new FileOutputStream(P12FILE), PASSWORD); + + // Check private keys still match certs + p12 = KeyStore.getInstance("pkcs12"); + p12.load(new FileInputStream(P12FILE), PASSWORD); + for (int i=0; i<SIZE; i++) { + String a = "p" + i; + X509Certificate x = (X509Certificate)p12.getCertificate(a); + X500Name name = (X500Name)x.getSubjectDN(); + if (!name.getCommonName().equals(""+i)) { + throw new Exception(a + "'s cert is " + name); + } + } + } +}
--- a/test/tools/launcher/Arrrghs.java Thu Jul 15 20:11:45 2010 -0700 +++ b/test/tools/launcher/Arrrghs.java Tue Jul 20 22:21:31 2010 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 + * @bug 5030233 6214916 6356475 6571029 6684582 6742159 4459600 6758881 6753938 * @summary Argument parsing validation. * @compile -XDignore.symbol.file Arrrghs.java TestHelper.java * @run main Arrrghs @@ -223,6 +223,20 @@ tr.checkPositive(); tr.isNotZeroOutput(); System.out.println(tr); + + // 6753938, test for non-negative exit value for an incorrectly formed + // command line, '% java' + tr = TestHelper.doExec(TestHelper.javaCmd); + tr.checkNegative(); + tr.isNotZeroOutput(); + System.out.println(tr); + + // 6753938, test for non-negative exit value for an incorrectly formed + // command line, '% java -Xcomp' + tr = TestHelper.doExec(TestHelper.javaCmd, "-Xcomp"); + tr.checkNegative(); + tr.isNotZeroOutput(); + System.out.println(tr); } /*
--- a/test/tools/launcher/Makefile.SolarisRunpath Thu Jul 15 20:11:45 2010 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. - -# - -# This is a not quite automated Makefile to generate the Solaris -# binaries used for the SolarisRunpath.sh test. First, -# libraryCaller.java program must be compiled. Next, javah is called -# on the class file to generate the needed header file for the jni -# code. Then, 2 Solaris executables are generated in separate -# directories, a default one meant to be pointed to by LD_LIBRARY_PATH -# (this function returns 0) and another one for the data model -# specific LD_LIBRARY_PATH (this function returns the size of integers -# in the data model, 32 or 64). A better makefile would run, say -# isainfo -v, and generated binaries for all supported data models. -# To do this a mapping would be needed from data models to -# architecture dependent compiler options; e.g. 64 bit on sparc => -# -xarch=v9. Also, the settings for JINCLUDE, JAVAC, and JAVAH should -# come from the current build. The C compiler should be the one -# approved for the build. To be extra safe, the binaries should be -# generated on the oldest Solaris release supported by the current -# Java build. - -# Include directory in JRE or JDK install; e.g. -JINCLUDE=/java/re/jdk/1.4.1/latest/binaries/solaris-sparc/include - -# Path to javac executable; e.g. -JAVAC=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javac - -# Path to javah executable; e.g. -JAVAH=/java/re/jdk/1.4.1/promoted/fcs/b21/binaries/solaris-sparc/bin/javah - -# Path to C compiler; e.g. -CC=/java/devtools/sparc/SUNWspro/SC6.1/bin/cc - - -ARCH=`uname -p` - -# 32-bit Solaris Options -DM=32 -# Default architecture is fine for both sparc and x86 32-bit builds -OPTIONS= - -# 64-bit Solaris Options -#DM=64 -#OPTIONS=-xarch=v9 - - -all: libraryCaller.java libraryCaller.c - $(JAVAC) libraryCaller.java; \ - $(JAVAH) libraryCaller; \ - $(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=0 \ - $(OPTIONS) libraryCaller.c \ - -o lib/$(ARCH)/lib$(DM)/liblibrary.so; \ - $(CC) -G -I$(JINCLUDE) -I$(JINCLUDE)/solaris -DRETURN_VALUE=$(DM)\ - $(OPTIONS) libraryCaller.c \ - -o lib/$(ARCH)/lib$(DM)/lib$(DM)/liblibrary.so;
--- a/test/tools/launcher/UnicodeTest.sh Thu Jul 15 20:11:45 2010 -0700 +++ b/test/tools/launcher/UnicodeTest.sh Tue Jul 20 22:21:31 2010 -0700 @@ -54,7 +54,11 @@ echo "creating test source files" "$JAVAC" -d . "${TESTSRC}"/UnicodeTest.java -CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' ` +if [ "`uname -s | grep CYGWIN`" != "" ] ; then + CLASS_NAME=`"$JAVA" UnicodeTest | sed -e 's@\\r@@g' ` +else + CLASS_NAME=`"$JAVA" UnicodeTest` +fi if [ "$CLASS_NAME" = "" ] then
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/launcher/VerifyExceptions.java Tue Jul 20 22:21:31 2010 -0700 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6856415 + * @summary Checks to ensure that proper exceptions are thrown by java + * @compile -XDignore.symbol.file VerifyExceptions.java TestHelper.java + * @run main VerifyExceptions + */ + + +import java.io.File; +import java.io.FileNotFoundException; + + +public class VerifyExceptions { + + static void test6856415() { + // No pkcs library on win-x64, so we bail out. + if (TestHelper.is64Bit && TestHelper.isWindows) { + return; + } + StringBuilder sb = new StringBuilder(); + sb.append("public static void main(String... args) {\n"); + sb.append("java.security.Provider p = new sun.security.pkcs11.SunPKCS11(args[0]);\n"); + sb.append("java.security.Security.insertProviderAt(p, 1);\n"); + sb.append("}"); + File testJar = new File("Foo.jar"); + testJar.delete(); + try { + TestHelper.createJar(testJar, sb.toString()); + } catch (FileNotFoundException fnfe) { + throw new RuntimeException(fnfe); + } + TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javacCmd, + "-Djava.security.manager", "-jar", testJar.getName(), "foo.bak"); + tr.checkNegative(); + tr.contains("Exception in thread \"main\" java.security.AccessControlException: access denied (\"java.lang.RuntimePermission\" \"accessClassInPackage.sun.security.pkcs11\")\")"); + } + + public static void main(String... args) { + test6856415(); + } +}