--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/common/shared/Defs-javadoc.gmk Mon Jul 12 19:42:02 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/jdk/make/docs/Makefile Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/make/docs/Makefile Mon Jul 12 19:42:02 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/jdk/make/java/java/FILES_java.gmk Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/make/java/java/FILES_java.gmk Mon Jul 12 19:42:02 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/jdk/make/java/security/Makefile Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/make/java/security/Makefile Mon Jul 12 19:42:02 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/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/make/tools/src/build/tools/jarreorder/JarReorder.java Mon Jul 12 19:42:02 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/jdk/src/share/bin/emessages.h Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/bin/emessages.h Mon Jul 12 19:42:02 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/jdk/src/share/bin/java.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/bin/java.c Mon Jul 12 19:42:02 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/jdk/src/share/bin/java.h Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/bin/java.h Mon Jul 12 19:42:02 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/jdk/src/share/bin/jli_util.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/bin/jli_util.c Mon Jul 12 19:42:02 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/jdk/src/share/bin/jli_util.h Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/bin/jli_util.h Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/beans/XMLDecoder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLDecoder.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/beans/XMLEncoder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/beans/XMLEncoder.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/io/Bits.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/io/Bits.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/io/Closeable.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/io/Closeable.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/io/ObjectInput.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectInput.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/io/ObjectOutput.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/io/ObjectOutput.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/lang/AbstractStringBuilder.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/AutoCloseable.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/Character.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Character.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/String.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/lang/String.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/System.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/lang/System.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/lang/Throwable.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/lang/Throwable.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/net/Inet6Address.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/net/Inet6Address.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/nio/Bits.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/nio/Bits.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/nio/channels/FileLock.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/nio/channels/FileLock.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/util/DualPivotQuicksort.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/util/DualPivotQuicksort.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/util/Scanner.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/util/Scanner.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/util/logging/LogManager.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/java/util/logging/Logger.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/javax/imageio/stream/ImageInputStream.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/javax/sound/midi/MidiDevice.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/MidiDevice.java Mon Jul 12 19:42:02 2010 -0700
@@ -107,7 +107,7 @@
* @author Florian Bomers
*/
-public interface MidiDevice {
+public interface MidiDevice extends AutoCloseable {
/**
--- a/jdk/src/share/classes/javax/sound/midi/Receiver.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Receiver.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/javax/sound/midi/Transmitter.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/midi/Transmitter.java Mon Jul 12 19:42:02 2010 -0700
@@ -35,7 +35,7 @@
*
* @author Kara Kytle
*/
-public interface Transmitter {
+public interface Transmitter extends AutoCloseable {
/**
--- a/jdk/src/share/classes/javax/sound/sampled/Line.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/javax/sound/sampled/Line.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_ASCII.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/io/CharToByteDBCS_EBCDIC.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/launcher/LauncherHelper.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/net/httpserver/ExchangeImpl.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/Surrogate.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/Surrogate.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_32Coder.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/UTF_8.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UTF_8.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/UnicodeEncoder.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/EUC_TW.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/GB18030.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM33722.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/nio/cs/ext/IBM964.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/Credentials.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/EncryptedData.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbApRep.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApRep.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbAsRep.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbCred.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbCred.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbPriv.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbPriv.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbTgsRep.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/crypto/EType.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/pkcs12/PKCS12KeyStore.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Mon Jul 12 19:42:02 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/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Mon Jul 12 19:42:02 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/jdk/src/solaris/bin/java_md.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/solaris/bin/java_md.c Mon Jul 12 19:42:02 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/jdk/src/solaris/demo/jni/Poller/Poller.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/solaris/demo/jni/Poller/Poller.c Mon Jul 12 19:42:02 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/jdk/src/solaris/native/java/net/NetworkInterface.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/solaris/native/java/net/NetworkInterface.c Mon Jul 12 19:42:02 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/jdk/src/windows/bin/java_md.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/windows/bin/java_md.c Mon Jul 12 19:42:02 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/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/windows/classes/sun/nio/ch/WindowsSelectorImpl.java Mon Jul 12 19:42:02 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/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/src/windows/native/sun/nio/ch/WindowsSelectorImpl.c Mon Jul 12 19:42:02 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/jdk/test/Makefile Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/Makefile Mon Jul 12 19:42:02 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/jdk/test/ProblemList.txt Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/ProblemList.txt Mon Jul 12 19:42:02 2010 -0700
@@ -376,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
@@ -504,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
@@ -530,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
@@ -552,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
--- a/jdk/test/java/lang/String/Supplementary.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/lang/String/Supplementary.java Mon Jul 12 19:42:02 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/jdk/test/java/lang/StringBuffer/Supplementary.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/lang/StringBuffer/Supplementary.java Mon Jul 12 19:42:02 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/jdk/test/java/lang/StringBuilder/Supplementary.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/lang/StringBuilder/Supplementary.java Mon Jul 12 19:42:02 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/jdk/test/java/lang/Throwable/SuppressedExceptions.java Mon Jul 12 19:42:02 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/jdk/test/java/net/Authenticator/B4769350.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/net/Authenticator/B4769350.java Mon Jul 12 19:42:02 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/jdk/test/java/net/BindException/Test.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/net/BindException/Test.java Mon Jul 12 19:42:02 2010 -0700
@@ -180,7 +180,7 @@
while (addrs.hasMoreElements()) {
InetAddress ia = (InetAddress)addrs.nextElement();
- if (ia.isLoopbackAddress()) {
+ if (ia.isLoopbackAddress() || ia.isAnyLocalAddress()) {
continue;
}
--- a/jdk/test/java/net/Inet6Address/B6214234.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/net/Inet6Address/B6214234.java Mon Jul 12 19:42:02 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/jdk/test/java/net/ipv6tests/Tests.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/net/ipv6tests/Tests.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/BufferPoolMXBean/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/BufferPoolMXBean/Basic.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/MappedByteBuffer/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Basic.java Mon Jul 12 19:42:02 2010 -0700
@@ -24,6 +24,7 @@
/* @test
* @bug 4462336
* @summary Simple MappedByteBuffer tests
+ * @run main/othervm Basic
*/
import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/Force.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/Force.java Mon Jul 12 19:42:02 2010 -0700
@@ -24,6 +24,7 @@
/* @test
* @bug 4625907
* @summary Testing force()
+ * @run main/othervm Force
*/
import java.io.*;
--- a/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/MappedByteBuffer/ZeroMap.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousChannelGroup/Identity.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousDatagramChannel/Basic.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Basic.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/Lock.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousFileChannel/LotsOfWrites.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Mon Jul 12 19:42:02 2010 -0700
@@ -776,6 +776,7 @@
throw new RuntimeException("RuntimeException expected after timeout.");
ch.close();
+ server.close();
}
// returns ByteBuffer with random bytes
--- a/jdk/test/java/nio/channels/Channels/Basic2.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Basic2.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Channels/Write.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Channels/Write.java Mon Jul 12 19:42:02 2010 -0700
@@ -47,5 +47,6 @@
out.close();
fc.close();
fos.close();
+ testFile.delete();
}
}
--- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java Mon Jul 12 19:42:02 2010 -0700
@@ -82,8 +82,6 @@
}
throw x;
}
- if (shouldTimeout)
- throw new Exception("Receive did not time out");
break;
}
--- a/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/EmptyBuffer.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/ReceiveISA.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/SelectWhenRefused.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Args.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Args.java Mon Jul 12 19:42:02 2010 -0700
@@ -97,6 +97,8 @@
(long)Integer.MAX_VALUE << 3);
}});
+ fc.close();
+ f.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ClosedChannelTransfer.java Mon Jul 12 19:42:02 2010 -0700
@@ -38,6 +38,7 @@
test1(channel);
test2(channel);
channel.close();
+ file.delete();
}
static void test1(FileChannel channel) throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ExpandingMap.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Lock.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Lock.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapOverEnd.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapReadOnly.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/MapTest.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/MapTest.java Mon Jul 12 19:42:02 2010 -0700
@@ -23,6 +23,7 @@
/* @test
* @summary Test file mapping with FileChannel
+ * @run main/othervm MapTest
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Mode.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Mode.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Position.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Position.java Mon Jul 12 19:42:02 2010 -0700
@@ -63,6 +63,7 @@
c.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/Pread.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pread.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Pwrite.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Pwrite.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Read.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Read.java Mon Jul 12 19:42:02 2010 -0700
@@ -80,6 +80,7 @@
c.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/ReadFull.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadFull.java Mon Jul 12 19:42:02 2010 -0700
@@ -54,5 +54,6 @@
fc.close();
fis.close();
+ blah.delete();
}
}
--- a/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReadToLimit.java Mon Jul 12 19:42:02 2010 -0700
@@ -48,6 +48,7 @@
throw new Exception("Test failed");
fc.close();
fis.close();
+ blah.delete();
}
/**
--- a/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ReleaseOnCloseDeadlock.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/ScatteringRead.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Size.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Size.java Mon Jul 12 19:42:02 2010 -0700
@@ -24,6 +24,7 @@
/* @test
* @bug 4563125
* @summary Test size method of FileChannel
+ * @run main/othervm Size
*/
import java.io.*;
--- a/jdk/test/java/nio/channels/FileChannel/Transfer.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfer.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToChannel.java Mon Jul 12 19:42:02 2010 -0700
@@ -51,6 +51,8 @@
test1();
test2();
in.close();
+ file.delete();
+ outFile.delete();
}
static void test1() throws Exception {
--- a/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TransferToNonWritable.java Mon Jul 12 19:42:02 2010 -0700
@@ -43,6 +43,9 @@
throw new RuntimeException("Test failed");
} catch (NonWritableChannelException nwce) {
// Correct result
+ } finally {
+ channel.close();
+ blah.delete();
}
}
}
--- a/jdk/test/java/nio/channels/FileChannel/Transfers.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Transfers.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/TryLock.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/TryLock.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/FileChannel/Write.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/FileChannel/Write.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Pipe/NonBlocking.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/NonBlocking.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Pipe/SelectPipe.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Pipe/SelectPipe.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SelectionKey/AtomicAttachTest.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/BasicAccept.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicAccept.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/BasicConnect.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/BasicConnect.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/CheckLocking.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CheckLocking.java Mon Jul 12 19:42:02 2010 -0700
@@ -61,5 +61,7 @@
doSelect();
sk.interestOps(SelectionKey.OP_READ);
selector.wakeup();
+ sc.close();
+ selector.close();
}
}
--- a/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseInvalidatesKeys.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/CloseWhenKeyIdle.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/Connect.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/Connect.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/ConnectWrite.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/ConnectWrite.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/HelperSlowToDie.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/KeysReady.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/KeysReady.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/LotsOfChannels.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/LotsOfChannels.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/OutOfBand.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/RegAfterPreClose.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/SelectAndCancel.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectAndCancel.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/SelectorLimit.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/SelectorTest.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/SelectorTest.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/WakeupNow.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupNow.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/WakeupOverflow.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupOverflow.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/Selector/WakeupSpeed.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/Selector/WakeupSpeed.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/ServerSocketChannel/AcceptAddress.java Mon Jul 12 19:35:11 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/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/AdaptSocket.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/Bind.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Bind.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/Close.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Close.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseRegisteredChannel.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/CloseTimeoutChannel.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/IsConnectable.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/LocalAddress.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketInheritance.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/Trivial.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/Trivial.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/SocketChannel/UnboundSocketTests.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/etc/Shadow.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/etc/Shadow.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/ClosedStreams.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/charset/coders/BashStreams.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/BashStreams.java Mon Jul 12 19:42:02 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/jdk/test/java/nio/charset/coders/Surrogate.java Mon Jul 12 19:35:11 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/jdk/test/java/nio/charset/coders/Surrogates.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/nio/charset/coders/Surrogates.java Mon Jul 12 19:42:02 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/jdk/test/java/util/Arrays/Sorting.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/java/util/Arrays/Sorting.java Mon Jul 12 19:42:02 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/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.java Mon Jul 12 19:42:02 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/jdk/test/java/util/logging/AnonLoggerWeakRefLeak.sh Mon Jul 12 19:42:02 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/jdk/test/java/util/logging/LoggerWeakRefLeak.java Mon Jul 12 19:42:02 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/jdk/test/java/util/logging/LoggerWeakRefLeak.sh Mon Jul 12 19:42:02 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
--- a/jdk/test/sun/nio/ch/Basic.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/ch/Basic.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/ch/TempBuffer.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/ch/TempBuffer.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/cs/FindDecoderBugs.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/cs/FindDecoderBugs.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/cs/ReadZero.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/cs/ReadZero.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/cs/Test4206507.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/cs/Test4206507.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/cs/TestStringCoding.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestStringCoding.java Mon Jul 12 19:42:02 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/jdk/test/sun/nio/cs/TestX11CNS.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/nio/cs/TestX11CNS.java Mon Jul 12 19:42:02 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/jdk/test/sun/security/krb5/auto/SSL.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/security/krb5/auto/SSL.java Mon Jul 12 19:42:02 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/jdk/test/sun/security/krb5/etype/ETypeOrder.java Mon Jul 12 19:42:02 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/jdk/test/sun/security/krb5/ktab/HighestKvno.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/sun/security/krb5/ktab/HighestKvno.java Mon Jul 12 19:42:02 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/jdk/test/sun/security/pkcs12/PKCS12SameKeyId.java Mon Jul 12 19:42:02 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/jdk/test/tools/launcher/Arrrghs.java Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/tools/launcher/Arrrghs.java Mon Jul 12 19:42:02 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/jdk/test/tools/launcher/Makefile.SolarisRunpath Mon Jul 12 19:35:11 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/jdk/test/tools/launcher/UnicodeTest.sh Mon Jul 12 19:35:11 2010 -0700
+++ b/jdk/test/tools/launcher/UnicodeTest.sh Mon Jul 12 19:42:02 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/jdk/test/tools/launcher/VerifyExceptions.java Mon Jul 12 19:42:02 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();
+ }
+}
Binary file jdk/test/tools/launcher/lib/i386/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/i386/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib32/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/lib64/liblibrary.so has changed
Binary file jdk/test/tools/launcher/lib/sparc/lib64/liblibrary.so has changed