--- a/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45
722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46
8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47
+b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48
+5b8db585a33c3cc48e70e688ceee57dd9271dc5d jdk9-b49
--- a/.hgtags-top-repo Fri Feb 06 19:49:20 2015 +0300
+++ b/.hgtags-top-repo Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
+0064e246d83f6f9fc245c19b6d05041ecaf4b6d4 jdk9-b48
+d91ed1951b948210590ce1394bea5515357246ba jdk9-b49
--- a/common/autoconf/basics.m4 Fri Feb 06 19:49:20 2015 +0300
+++ b/common/autoconf/basics.m4 Mon Feb 09 09:52:48 2015 -0800
@@ -987,3 +987,26 @@
IS_RECONFIGURE=no
fi
])
+
+# Check for support for specific options in bash
+AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS],
+[
+ # Test if bash supports pipefail.
+ AC_MSG_CHECKING([if bash supports pipefail])
+ if ${BASH} -c 'set -o pipefail'; then
+ BASH_ARGS="$BASH_ARGS -o pipefail"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ AC_MSG_CHECKING([if bash supports errexit (-e)])
+ if ${BASH} -e -c 'true'; then
+ BASH_ARGS="$BASH_ARGS -e"
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ AC_SUBST(BASH_ARGS)
+])
--- a/common/autoconf/bootcycle-spec.gmk.in Fri Feb 06 19:49:20 2015 +0300
+++ b/common/autoconf/bootcycle-spec.gmk.in Mon Feb 09 09:52:48 2015 -0800
@@ -46,8 +46,12 @@
BOOT_JDK := $(JDK_IMAGE_DIR)
# The bootcycle build has a different output directory
-BUILD_OUTPUT:=@BUILD_OUTPUT@/bootcycle-build
-SJAVAC_SERVER_DIR:=$(subst @BUILD_OUTPUT@,$(BUILD_OUTPUT),$(SJAVAC_SERVER_DIR))
+OLD_BUILD_OUTPUT:=@BUILD_OUTPUT@
+BUILD_OUTPUT:=$(OLD_BUILD_OUTPUT)/bootcycle-build
+# The HOTSPOT_DIST dir is not defined relative to BUILD_OUTPUT in spec.gmk. Must not
+# use space in this patsubst to avoid leading space in HOTSPOT_DIST.
+HOTSPOT_DIST:=$(patsubst $(OLD_BUILD_OUTPUT)%,$(BUILD_OUTPUT)%,$(HOTSPOT_DIST))
+SJAVAC_SERVER_DIR:=$(patsubst $(OLD_BUILD_OUTPUT)%, $(BUILD_OUTPUT)%, $(SJAVAC_SERVER_DIR))
JAVA_CMD:=$(BOOT_JDK)/bin/java
JAVAC_CMD:=$(BOOT_JDK)/bin/javac
--- a/common/autoconf/configure.ac Fri Feb 06 19:49:20 2015 +0300
+++ b/common/autoconf/configure.ac Mon Feb 09 09:52:48 2015 -0800
@@ -113,6 +113,7 @@
# Setup tools that requires more complex handling, or that is not needed by the configure script.
BASIC_SETUP_COMPLEX_TOOLS
+BASIC_CHECK_BASH_OPTIONS
# Check if pkg-config is available.
PKG_PROG_PKG_CONFIG
--- a/common/autoconf/generated-configure.sh Fri Feb 06 19:49:20 2015 +0300
+++ b/common/autoconf/generated-configure.sh Mon Feb 09 09:52:48 2015 -0800
@@ -853,6 +853,7 @@
OS_VERSION_MINOR
OS_VERSION_MAJOR
PKG_CONFIG
+BASH_ARGS
CODESIGN
XATTR
DSYMUTIL
@@ -3522,6 +3523,9 @@
+# Check for support for specific options in bash
+
+
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -4329,7 +4333,7 @@
#CUSTOM_AUTOCONF_INCLUDE
# Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1420811523
+DATE_WHEN_GENERATED=1421247827
###############################################################################
#
@@ -19609,6 +19613,32 @@
fi
+ # Test if bash supports pipefail.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports pipefail" >&5
+$as_echo_n "checking if bash supports pipefail... " >&6; }
+ if ${BASH} -c 'set -o pipefail'; then
+ BASH_ARGS="$BASH_ARGS -o pipefail"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports errexit (-e)" >&5
+$as_echo_n "checking if bash supports errexit (-e)... " >&6; }
+ if ${BASH} -e -c 'true'; then
+ BASH_ARGS="$BASH_ARGS -e"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+
+
+
+
# Check if pkg-config is available.
@@ -27408,8 +27438,8 @@
# The trailing space for everyone except PATH is no typo, but is needed due
# to trailing \ in the Windows paths. These will be stripped later.
$ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
- $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE\;$include \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
- $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB\;$lib \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+ $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
+ $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
$ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
--- a/common/autoconf/spec.gmk.in Fri Feb 06 19:49:20 2015 +0300
+++ b/common/autoconf/spec.gmk.in Mon Feb 09 09:52:48 2015 -0800
@@ -78,6 +78,11 @@
OUTPUT_SYNC_SUPPORTED:=@OUTPUT_SYNC_SUPPORTED@
OUTPUT_SYNC:=@OUTPUT_SYNC@
+# Override the shell with bash
+BASH:=@BASH@
+BASH_ARGS:=@BASH_ARGS@
+SHELL:=$(BASH) $(BASH_ARGS)
+
# The "human readable" name of this configuration
CONF_NAME:=@CONF_NAME@
@@ -243,7 +248,7 @@
HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot
JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
-TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake
+TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
HOTSPOT_DIST=@HOTSPOT_DIST@
@@ -495,7 +500,6 @@
# Tools adhering to a minimal and common standard of posix compliance.
AWK:=@AWK@
BASENAME:=@BASENAME@
-BASH:=@BASH@
CAT:=@CAT@
CCACHE:=@CCACHE@
# CD is going away, but remains to cater for legacy makefiles.
--- a/common/bin/unshuffle_list.txt Fri Feb 06 19:49:20 2015 +0300
+++ b/common/bin/unshuffle_list.txt Mon Feb 09 09:52:48 2015 -0800
@@ -123,6 +123,7 @@
jdk/src/java.base/share/classes/java/math : jdk/src/share/classes/java/math
jdk/src/java.base/share/classes/java/net : jdk/src/share/classes/java/net
jdk/src/java.base/share/classes/java/nio : jdk/src/share/classes/java/nio
+jdk/src/java.base/share/classes/java/security/acl : jdk/src/share/classes/java/security/acl
jdk/src/java.base/share/classes/java/security/cert : jdk/src/share/classes/java/security/cert
jdk/src/java.base/share/classes/java/security/interfaces : jdk/src/share/classes/java/security/interfaces
jdk/src/java.base/share/classes/java/security : jdk/src/share/classes/java/security
@@ -179,6 +180,7 @@
jdk/src/java.base/share/classes/sun/nio/cs : jdk/src/share/classes/sun/nio/cs
jdk/src/java.base/share/classes/sun/nio/fs : jdk/src/share/classes/sun/nio/fs
jdk/src/java.base/share/classes/sun/reflect : jdk/src/share/classes/sun/reflect
+jdk/src/java.base/share/classes/sun/security/acl : jdk/src/share/classes/sun/security/acl
jdk/src/java.base/share/classes/sun/security/action : jdk/src/share/classes/sun/security/action
jdk/src/java.base/share/classes/sun/security/internal : jdk/src/share/classes/sun/security/internal
jdk/src/java.base/share/classes/sun/security/jca : jdk/src/share/classes/sun/security/jca
@@ -1211,8 +1213,6 @@
jdk/src/java.rmi/unix/bin/java-rmi.cgi.sh : jdk/src/solaris/bin/java-rmi.cgi.sh
jdk/src/java.scripting/share/classes/javax/script : jdk/src/share/classes/javax/script
jdk/src/java.scripting/share/classes/com/sun/tools/script/shell : jdk/src/share/classes/com/sun/tools/script/shell
-jdk/src/java.security.acl/share/classes/java/security/acl : jdk/src/share/classes/java/security/acl
-jdk/src/java.security.acl/share/classes/sun/security/acl : jdk/src/share/classes/sun/security/acl
jdk/src/java.security.jgss/macosx/native/libosxkrb5/nativeccache.c : jdk/src/share/native/sun/security/krb5/nativeccache.c
jdk/src/java.security.jgss/macosx/native/libosxkrb5/SCDynamicStoreConfig.m : jdk/src/macosx/native/sun/security/krb5/SCDynamicStoreConfig.m
jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos : jdk/src/share/classes/javax/security/auth/kerberos
--- a/corba/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/corba/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
+a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48
+9285d14eb7b6b0815679bae98dd936dbc136218d jdk9-b49
--- a/hotspot/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -450,3 +450,5 @@
5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
+cc775a4a24c7f5d9e624b4205e9fbd48a17331f6 jdk9-b48
+360cd1fc42f10941a9fd17cc32d5b85a22d12a0b jdk9-b49
--- a/hotspot/make/aix/Makefile Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/aix/Makefile Mon Feb 09 09:52:48 2015 -0800
@@ -246,8 +246,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
--- a/hotspot/make/aix/makefiles/mapfile-vers-debug Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/aix/makefiles/mapfile-vers-debug Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/aix/makefiles/mapfile-vers-product Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/aix/makefiles/mapfile-vers-product Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,7 @@
JVM_GetMethodIxNameUTF;
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/aix/makefiles/xlc.make Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/aix/makefiles/xlc.make Mon Feb 09 09:52:48 2015 -0800
@@ -74,6 +74,12 @@
# no xlc counterpart for -fcheck-new
# CFLAGS += -fcheck-new
+# We need to define this on the command line if we want to use the the
+# predefined format specifiers from "inttypes.h". Otherwise system headrs
+# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS
+# in globalDefinitions.hpp
+CFLAGS += -D__STDC_FORMAT_MACROS
+
ARCHFLAG = -q64
CFLAGS += $(ARCHFLAG)
--- a/hotspot/make/bsd/Makefile Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/Makefile Mon Feb 09 09:52:48 2015 -0800
@@ -240,8 +240,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
--- a/hotspot/make/bsd/makefiles/dtrace.make Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/dtrace.make Mon Feb 09 09:52:48 2015 -0800
@@ -179,23 +179,23 @@
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -header > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1 ; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS)Index.h: $(GENOFFS)
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -index > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1 ; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS).cpp: $(GENOFFS) $(JVMOFFS).h $(JVMOFFS)Index.h
$(QUIETLY) DYLD_LIBRARY_PATH=.:$(DYLD_LIBRARY_PATH) ./$(GENOFFS) -table > $@.tmp; touch $@; \
- if [ `diff $@.tmp $@ > /dev/null 2>&1; echo $$?` -ne 0 ] ; \
- then rm -f $@; mv $@.tmp $@; \
- else rm -f $@.tmp; \
+ if diff $@.tmp $@ > /dev/null 2>&1; \
+ then rm -f $@.tmp; \
+ else rm -f $@; mv $@.tmp $@; \
fi
$(JVMOFFS.o): $(JVMOFFS).h $(JVMOFFS).cpp
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,7 @@
_JVM_GetMethodIxSignatureUTF
_JVM_GetMethodParameters
_JVM_GetMethodTypeAnnotations
+ _JVM_GetNanoTimeAdjustment
_JVM_GetPrimitiveArrayElement
_JVM_GetProtectionDomain
_JVM_GetStackAccessControlContext
--- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,7 @@
_JVM_GetMethodIxSignatureUTF
_JVM_GetMethodParameters
_JVM_GetMethodTypeAnnotations
+ _JVM_GetNanoTimeAdjustment
_JVM_GetPrimitiveArrayElement
_JVM_GetProtectionDomain
_JVM_GetStackAccessControlContext
--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/bsd/makefiles/mapfile-vers-product Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-product Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/bsd/makefiles/universal.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/bsd/makefiles/universal.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -59,7 +59,7 @@
# Package built libraries in a universal binary
$(UNIVERSAL_LIPO_LIST):
- BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`"; \
+ BUILT_LIPO_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_LIPO_FILES}" ]; then \
$(MKDIR) -p $(shell dirname $@); \
lipo -create -output $@ $${BUILT_LIPO_FILES}; \
@@ -70,7 +70,7 @@
# - copies directories; including empty dirs
# - copies files, symlinks, other non-directory files
$(UNIVERSAL_COPY_LIST):
- BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`"; \
+ BUILT_COPY_FILES="`find $(EXPORT_JRE_LIB_DIR)/{i386,amd64}/$(subst $(EXPORT_JRE_LIB_DIR)/,,$@) -prune 2>/dev/null`" || test $$? = "1"; \
if [ -n "$${BUILT_COPY_FILES}" ]; then \
for i in $${BUILT_COPY_FILES}; do \
$(MKDIR) -p $(shell dirname $@); \
--- a/hotspot/make/linux/Makefile Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/linux/Makefile Mon Feb 09 09:52:48 2015 -0800
@@ -246,8 +246,7 @@
XSLT_CHECK = $(REMOTE) $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(REMOTE) $(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
--- a/hotspot/make/linux/makefiles/build_vm_def.sh Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-# If we're cross compiling use that path for nm
-if [ "$CROSS_COMPILE_ARCH" != "" ]; then
-NM=$ALT_COMPILER_PATH/nm
-else
-NM=nm
-fi
-
-$NM --defined-only $* \
- | awk '{
- if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";"
- if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";"
- if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";"
- }' \
- | sort -u
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/linux/makefiles/mapfile-vers-product Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/make/linux/makefiles/vm.make Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/linux/makefiles/vm.make Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -239,8 +239,14 @@
rm -f $@
cat $^ > $@
+VMDEF_PAT = ^_ZTV
+VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT)
+VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT)
+VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT)
+
vm.def: $(Res_Files) $(Obj_Files)
- sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
+ $(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \
+ awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@
mapfile_ext:
rm -f $@
@@ -334,10 +340,8 @@
rm -f $@.1; ln -s $@ $@.1; \
if [ \"$(CROSS_COMPILE_ARCH)\" = \"\" ] ; then \
if [ -x /usr/sbin/selinuxenabled ] ; then \
- /usr/sbin/selinuxenabled; \
- if [ $$? = 0 ] ; then \
- /usr/bin/chcon -t textrel_shlib_t $@; \
- if [ $$? != 0 ]; then \
+ if /usr/sbin/selinuxenabled; then \
+ if ! /usr/bin/chcon -t textrel_shlib_t $@; then \
echo "ERROR: Cannot chcon $@"; \
fi \
fi \
--- a/hotspot/make/sa.files Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/sa.files Mon Feb 09 09:52:48 2015 -0800
@@ -39,6 +39,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/classfile/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/compiler/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/*.java \
@@ -49,8 +50,10 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/cdbg/basic/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/dummy/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/linux/sparc/*.java \
@@ -71,6 +74,7 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/win32/coff/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/ia64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windbg/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/debugger/windows/amd64/*.java \
@@ -101,6 +105,8 @@
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/solaris_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/sparc/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/x86/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_amd64/*.java \
+$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/win32_x86/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/runtime/ppc64/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/*.java \
$(AGENT_SRC_DIR)/sun/jvm/hotspot/tools/jcore/*.java \
--- a/hotspot/make/solaris/Makefile Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/solaris/Makefile Mon Feb 09 09:52:48 2015 -0800
@@ -190,8 +190,7 @@
XSLT_CHECK = $(RUN.JAVAP) javax.xml.transform.TransformerFactory
# If not found then fail fast.
check_j2se_version:
- $(QUIETLY) $(XSLT_CHECK) > /dev/null 2>&1; \
- if [ $$? -ne 0 ]; then \
+ $(QUIETLY) if ! $(XSLT_CHECK) > /dev/null 2>&1; then \
$(RUN.JAVA) -version; \
echo "*** An XSLT processor (J2SE 1.4.x or newer) is required" \
"to bootstrap this build" 1>&2; \
--- a/hotspot/make/solaris/makefiles/dtrace.make Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/solaris/makefiles/dtrace.make Mon Feb 09 09:52:48 2015 -0800
@@ -171,11 +171,11 @@
./lib$(GENOFFS).so
CONDITIONALLY_UPDATE_JVMOFFS_TARGET = \
- cmp -s $@ $@.tmp; \
- case $$? in \
- 0) rm -f $@.tmp;; \
- *) rm -f $@ && mv $@.tmp $@ && echo Updated $@;; \
- esac
+ if cmp -s $@ $@.tmp; then \
+ rm -f $@.tmp; \
+ else \
+ rm -f $@ && mv $@.tmp $@ && echo Updated $@; \
+ fi
# $@.tmp is created first to avoid an empty $(JVMOFFS).h if an error occurs.
$(JVMOFFS).h: $(GENOFFS)
--- a/hotspot/make/solaris/makefiles/mapfile-vers Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/make/solaris/makefiles/mapfile-vers Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,7 @@
JVM_GetMethodIxSignatureUTF;
JVM_GetMethodParameters;
JVM_GetMethodTypeAnnotations;
+ JVM_GetNanoTimeAdjustment;
JVM_GetPrimitiveArrayElement;
JVM_GetProtectionDomain;
JVM_GetStackAccessControlContext;
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -567,16 +567,21 @@
inline void load_with_trap_null_check(Register d, int si16, Register s1);
// Load heap oop and decompress. Loaded oop may not be null.
- inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg);
+ // Specify tmp to save one cycle.
+ inline void load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1 = noreg,
+ Register tmp = noreg);
+ // Store heap oop and decompress. Decompressed oop may not be null.
+ // Specify tmp register if d should not be changed.
inline void store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1,
- /*specify if d must stay uncompressed*/ Register tmp = noreg);
+ Register tmp = noreg);
// Null allowed.
inline void load_heap_oop(Register d, RegisterOrConstant offs, Register s1 = noreg);
// Encode/decode heap oop. Oop may not be null, else en/decoding goes wrong.
+ // src == d allowed.
inline Register encode_heap_oop_not_null(Register d, Register src = noreg);
- inline void decode_heap_oop_not_null(Register d);
+ inline Register decode_heap_oop_not_null(Register d, Register src = noreg);
// Null allowed.
inline void decode_heap_oop(Register d);
--- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -311,11 +311,14 @@
ld(d, si16, s1);
}
-inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) {
+inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {
if (UseCompressedOops) {
- lwz(d, offs, s1);
+ // In disjoint mode decoding can save a cycle if src != dst.
+ Register narrowOop = (tmp != noreg && Universe::narrow_oop_base_disjoint()) ? tmp : d;
+ lwz(narrowOop, offs, s1);
// Attention: no null check here!
- decode_heap_oop_not_null(d);
+ Register res = decode_heap_oop_not_null(d, narrowOop);
+ assert(res == d, "caller will not consume loaded value");
} else {
ld(d, offs, s1);
}
@@ -340,26 +343,36 @@
}
inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {
- Register current = (src!=noreg) ? src : d; // Compressed oop is in d if no src provided.
- if (Universe::narrow_oop_base() != NULL) {
+ Register current = (src != noreg) ? src : d; // Oop to be compressed is in d if no src provided.
+ if (Universe::narrow_oop_base_overlaps()) {
sub(d, current, R30);
current = d;
}
if (Universe::narrow_oop_shift() != 0) {
- srdi(d, current, LogMinObjAlignmentInBytes);
+ rldicl(d, current, 64-Universe::narrow_oop_shift(), 32); // Clears the upper bits.
current = d;
}
return current; // Encoded oop is in this register.
}
-inline void MacroAssembler::decode_heap_oop_not_null(Register d) {
+inline Register MacroAssembler::decode_heap_oop_not_null(Register d, Register src) {
+ if (Universe::narrow_oop_base_disjoint() && src != noreg && src != d &&
+ Universe::narrow_oop_shift() != 0) {
+ mr(d, R30);
+ rldimi(d, src, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+ return d;
+ }
+
+ Register current = (src != noreg) ? src : d; // Compressed oop is in d if no src provided.
if (Universe::narrow_oop_shift() != 0) {
- assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
- sldi(d, d, LogMinObjAlignmentInBytes);
+ sldi(d, current, Universe::narrow_oop_shift());
+ current = d;
}
if (Universe::narrow_oop_base() != NULL) {
- add(d, d, R30);
+ add(d, current, R30);
+ current = d;
}
+ return current; // Decoded oop is in this register.
}
inline void MacroAssembler::decode_heap_oop(Register d) {
@@ -368,13 +381,7 @@
cmpwi(CCR0, d, 0);
beq(CCR0, isNull);
}
- if (Universe::narrow_oop_shift() != 0) {
- assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");
- sldi(d, d, LogMinObjAlignmentInBytes);
- }
- if (Universe::narrow_oop_base() != NULL) {
- add(d, d, R30);
- }
+ decode_heap_oop_not_null(d);
bind(isNull);
}
--- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -172,15 +172,15 @@
// Load the invoker, as MH -> MH.form -> LF.vmentry
__ verify_oop(recv);
- __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv);
+ __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), recv, temp2);
__ verify_oop(method_temp);
- __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp);
+ __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
__ verify_oop(method_temp);
- // the following assumes that a Method* is normally compressed in the vmtarget field:
+ // The following assumes that a Method* is normally compressed in the vmtarget field:
__ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp);
if (VerifyMethodHandles && !for_compiler_entry) {
- // make sure recv is already on stack
+ // Make sure recv is already on stack.
__ ld(temp2, in_bytes(Method::const_offset()), method_temp);
__ load_sized_value(temp2, in_bytes(ConstMethod::size_of_parameters_offset()), temp2,
sizeof(u2), /*is_signed*/ false);
@@ -259,8 +259,9 @@
}
if (TraceMethodHandles) {
- if (tmp_mh != noreg)
+ if (tmp_mh != noreg) {
__ mr(R23_method_handle, tmp_mh); // make stub happy
+ }
trace_method_handle_interpreter_entry(_masm, iid);
}
@@ -332,7 +333,7 @@
if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
Label L_ok;
Register temp2_defc = temp2;
- __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+ __ load_heap_oop_not_null(temp2_defc, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
__ verify_klass_ptr(temp2_defc);
__ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -407,7 +408,7 @@
}
Register temp2_intf = temp2;
- __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg);
+ __ load_heap_oop_not_null(temp2_intf, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes()), member_reg, temp3);
load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
__ verify_klass_ptr(temp2_intf);
@@ -464,7 +465,7 @@
strstr(adaptername, "linkTo") == NULL); // static linkers don't have MH
const char* mh_reg_name = has_mh ? "R23_method_handle" : "G23";
tty->print_cr("MH %s %s="INTPTR_FORMAT " sp=" INTPTR_FORMAT,
- adaptername, mh_reg_name, (intptr_t) mh, (intptr_t) entry_sp);
+ adaptername, mh_reg_name, (intptr_t) mh, entry_sp);
if (Verbose) {
tty->print_cr("Registers:");
@@ -535,23 +536,22 @@
BLOCK_COMMENT("trace_method_handle {");
- int nbytes_save = 10 * 8; // 10 volatile gprs
- __ save_LR_CR(R0);
- __ mr(R0, R1_SP); // saved_sp
- assert(Assembler::is_simm(-nbytes_save, 16), "Overwriting R0");
- // Push_frame_reg_args only uses R0 if nbytes_save is wider than 16 bit.
- __ push_frame_reg_args(nbytes_save, R0);
- __ save_volatile_gprs(R1_SP, frame::abi_reg_args_size); // Except R0.
+ const Register tmp = R11; // Will be preserved.
+ const int nbytes_save = 11*8; // volatile gprs except R0
+ __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
+ __ save_LR_CR(tmp); // save in old frame
- __ load_const(R3_ARG1, (address)adaptername);
+ __ mr(R5_ARG3, R1_SP); // saved_sp
+ __ push_frame_reg_args(nbytes_save, tmp);
+
+ __ load_const_optimized(R3_ARG1, (address)adaptername, tmp);
__ mr(R4_ARG2, R23_method_handle);
- __ mr(R5_ARG3, R0); // saved_sp
__ mr(R6_ARG4, R1_SP);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub));
- __ restore_volatile_gprs(R1_SP, 112); // Except R0.
__ pop_frame();
- __ restore_LR_CR(R0);
+ __ restore_LR_CR(tmp);
+ __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
BLOCK_COMMENT("} trace_method_handle");
}
--- a/hotspot/src/cpu/ppc/vm/ppc.ad Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/ppc/vm/ppc.ad Mon Feb 09 09:52:48 2015 -0800
@@ -1,6 +1,6 @@
//
-// Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
-// Copyright 2012, 2014 SAP AG. All rights reserved.
+// Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+// Copyright 2012, 2015 SAP AG. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -2698,7 +2698,7 @@
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
- AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+ AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else {
@@ -2727,7 +2727,7 @@
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else if (constant_reloc == relocInfo::metadata_type) {
- AddressLiteral a = __ allocate_metadata_address((Metadata *)val);
+ AddressLiteral a = __ constant_metadata_address((Metadata *)val);
const_toc_addr = __ address_constant((address)a.value(), RelocationHolder::none);
__ relocate(a.rspec());
} else { // non-oop pointers, e.g. card mark base, heap top
@@ -6029,6 +6029,20 @@
ins_pipe(pipe_class_default);
%}
+// Optimize DecodeN for disjoint base.
+// Load base of compressed oops into a register
+instruct loadBase(iRegLdst dst) %{
+ effect(DEF dst);
+
+ format %{ "MR $dst, r30_heapbase" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_or);
+ __ mr($dst$$Register, R30);
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
// Loading ConN must be postalloc expanded so that edges between
// the nodes are safe. They may not interfere with a safepoint.
// GL TODO: This needs three instructions: better put this into the constant pool.
@@ -6724,13 +6738,12 @@
ins_pipe(pipe_class_default);
%}
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodeP_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodeP_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodeP src));
- predicate(false /* TODO: PPC port Universe::narrow_oop_base_disjoint()*/);
-
- format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+ predicate(Universe::narrow_oop_base_disjoint());
+
+ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -6745,7 +6758,7 @@
effect(TEMP crx);
predicate(n->bottom_type()->make_ptr()->ptr() != TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
- true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+ Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $crx, $src \t// postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop(dst, src, crx));
@@ -6756,7 +6769,7 @@
match(Set dst (EncodeP src));
predicate(n->bottom_type()->make_ptr()->ptr() == TypePtr::NotNull &&
Universe::narrow_oop_shift() != 0 &&
- true /* TODO: PPC port Universe::narrow_oop_base_overlaps()*/);
+ Universe::narrow_oop_base_overlaps());
format %{ "EncodeP $dst, $src\t// $src != Null, postalloc expanded" %}
postalloc_expand( postalloc_expand_encode_oop_not_null(dst, src) );
@@ -6876,6 +6889,7 @@
n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
+ ins_cost(4 * DEFAULT_COST); // Should be more expensive than decodeN_Disjoint_isel_Ex.
effect(TEMP crx);
format %{ "DecodeN $dst, $src \t// Kills $crx, postalloc expanded" %}
@@ -6897,6 +6911,106 @@
ins_pipe(pipe_class_default);
%}
+// Optimize DecodeN for disjoint base.
+// Shift narrow oop and or it into register that already contains the heap base.
+// Base == dst must hold, and is assured by construction in postaloc_expand.
+instruct decodeN_mergeDisjoint(iRegPdst dst, iRegNsrc src, iRegLsrc base) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP base);
+ predicate(false);
+
+ format %{ "RLDIMI $dst, $src, shift, 32-shift \t// DecodeN (disjoint base)" %}
+ size(4);
+ ins_encode %{
+ // TODO: PPC port $archOpcode(ppc64Opcode_rldimi);
+ __ rldimi($dst$$Register, $src$$Register, Universe::narrow_oop_shift(), 32-Universe::narrow_oop_shift());
+ %}
+ ins_pipe(pipe_class_default);
+%}
+
+// Optimize DecodeN for disjoint base.
+// This node requires only one cycle on the critical path.
+// We must postalloc_expand as we can not express use_def effects where
+// the used register is L and the def'ed register P.
+instruct decodeN_Disjoint_notNull_Ex(iRegPdst dst, iRegNsrc src) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP_DEF dst);
+ predicate((n->bottom_type()->is_oopptr()->ptr() == TypePtr::NotNull ||
+ n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
+ Universe::narrow_oop_base_disjoint());
+ ins_cost(DEFAULT_COST);
+
+ format %{ "MOV $dst, R30 \t\n"
+ "RLDIMI $dst, $src, shift, 32-shift \t// decode with disjoint base" %}
+ postalloc_expand %{
+ loadBaseNode *n1 = new loadBaseNode();
+ n1->add_req(NULL);
+ n1->_opnds[0] = op_dst;
+
+ decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+ n2->add_req(n_region, n_src, n1);
+ n2->_opnds[0] = op_dst;
+ n2->_opnds[1] = op_src;
+ n2->_opnds[2] = op_dst;
+ n2->_bottom_type = _bottom_type;
+
+ ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+ nodes->push(n1);
+ nodes->push(n2);
+ %}
+%}
+
+instruct decodeN_Disjoint_isel_Ex(iRegPdst dst, iRegNsrc src, flagsReg crx) %{
+ match(Set dst (DecodeN src));
+ effect(TEMP_DEF dst, TEMP crx);
+ predicate((n->bottom_type()->is_oopptr()->ptr() != TypePtr::NotNull &&
+ n->bottom_type()->is_oopptr()->ptr() != TypePtr::Constant) &&
+ Universe::narrow_oop_base_disjoint() && VM_Version::has_isel());
+ ins_cost(3 * DEFAULT_COST);
+
+ format %{ "DecodeN $dst, $src \t// decode with disjoint base using isel" %}
+ postalloc_expand %{
+ loadBaseNode *n1 = new loadBaseNode();
+ n1->add_req(NULL);
+ n1->_opnds[0] = op_dst;
+
+ cmpN_reg_imm0Node *n_compare = new cmpN_reg_imm0Node();
+ n_compare->add_req(n_region, n_src);
+ n_compare->_opnds[0] = op_crx;
+ n_compare->_opnds[1] = op_src;
+ n_compare->_opnds[2] = new immN_0Oper(TypeNarrowOop::NULL_PTR);
+
+ decodeN_mergeDisjointNode *n2 = new decodeN_mergeDisjointNode();
+ n2->add_req(n_region, n_src, n1);
+ n2->_opnds[0] = op_dst;
+ n2->_opnds[1] = op_src;
+ n2->_opnds[2] = op_dst;
+ n2->_bottom_type = _bottom_type;
+
+ cond_set_0_ptrNode *n_cond_set = new cond_set_0_ptrNode();
+ n_cond_set->add_req(n_region, n_compare, n2);
+ n_cond_set->_opnds[0] = op_dst;
+ n_cond_set->_opnds[1] = op_crx;
+ n_cond_set->_opnds[2] = op_dst;
+ n_cond_set->_bottom_type = _bottom_type;
+
+ assert(ra_->is_oop(this) == true, "A decodeN node must produce an oop!");
+ ra_->set_oop(n_cond_set, true);
+
+ ra_->set_pair(n1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n_compare->_idx, ra_->get_reg_second(n_crx), ra_->get_reg_first(n_crx));
+ ra_->set_pair(n2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+ ra_->set_pair(n_cond_set->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this));
+
+ nodes->push(n1);
+ nodes->push(n_compare);
+ nodes->push(n2);
+ nodes->push(n_cond_set);
+ %}
+%}
+
// src != 0, shift != 0, base != 0
instruct decodeN_notNull_addBase_Ex(iRegPdst dst, iRegNsrc src) %{
match(Set dst (DecodeN src));
@@ -6904,6 +7018,7 @@
n->bottom_type()->is_oopptr()->ptr() == TypePtr::Constant) &&
Universe::narrow_oop_shift() != 0 &&
Universe::narrow_oop_base() != 0);
+ ins_cost(2 * DEFAULT_COST);
format %{ "DecodeN $dst, $src \t// $src != NULL, postalloc expanded" %}
postalloc_expand( postalloc_expand_decode_oop_not_null(dst, src));
@@ -6973,13 +7088,12 @@
ins_pipe(pipe_class_default);
%}
-// base != 0
-// 32G aligned narrow oop base.
-instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{
+// Disjoint narrow oop base.
+instruct encodePKlass_Disjoint(iRegNdst dst, iRegPsrc src) %{
match(Set dst (EncodePKlass src));
predicate(false /* TODO: PPC port Universe::narrow_klass_base_disjoint()*/);
- format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with 32G aligned base" %}
+ format %{ "EXTRDI $dst, $src, #32, #3 \t// encode with disjoint base" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_rldicl);
@@ -7486,7 +7600,7 @@
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
__ cmpxchgd($crx$$CondRegister, R0, $oldVal$$Register, $newVal$$Register, $mem_ptr$$Register,
- MacroAssembler::MemBarNone, MacroAssembler::cmpxchgx_hint_atomic_update(),
+ MacroAssembler::MemBarAcq, MacroAssembler::cmpxchgx_hint_atomic_update(),
noreg, NULL, true);
%}
ins_pipe(pipe_class_default);
@@ -10476,7 +10590,7 @@
match(Set crx (CmpN src1 src2));
size(4);
- ins_cost(DEFAULT_COST);
+ ins_cost(2);
format %{ "CMPLW $crx, $src1, $src2 \t// compressed ptr" %}
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_cmpl);
@@ -10488,7 +10602,7 @@
instruct cmpN_reg_imm0(flagsReg crx, iRegNsrc src1, immN_0 src2) %{
match(Set crx (CmpN src1 src2));
// Make this more expensive than zeroCheckN_iReg_imm0.
- ins_cost(DEFAULT_COST);
+ ins_cost(2);
format %{ "CMPLWI $crx, $src1, $src2 \t// compressed ptr" %}
size(4);
@@ -10508,6 +10622,7 @@
_kids[0]->_leaf->as_Bool()->_test._test == BoolTest::ne &&
_leaf->as_If()->_prob >= PROB_LIKELY_MAG(4) &&
Matcher::branches_to_uncommon_trap(_leaf));
+ ins_cost(1); // Should not be cheaper than zeroCheckN.
ins_is_TrapBasedCheckNode(true);
@@ -10889,7 +11004,7 @@
instruct partialSubtypeCheck(iRegPdst result, iRegP_N2P subklass, iRegP_N2P superklass,
iRegPdst tmp_klass, iRegPdst tmp_arrayptr) %{
match(Set result (PartialSubtypeCheck subklass superklass));
- effect(TEMP result, TEMP tmp_klass, TEMP tmp_arrayptr);
+ effect(TEMP_DEF result, TEMP tmp_klass, TEMP tmp_arrayptr);
ins_cost(DEFAULT_COST*10);
format %{ "PartialSubtypeCheck $result = ($subklass instanceOf $superklass) tmp: $tmp_klass, $tmp_arrayptr" %}
@@ -11000,7 +11115,7 @@
predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
- effect(TEMP result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
ins_cost(150);
format %{ "String IndexOf CSCL1 $haystack[0..$haycnt], $needleImm+$offsetImm[0..$needlecntImm]"
@@ -11037,7 +11152,7 @@
iRegIdst tmp1, iRegIdst tmp2,
flagsRegCR0 cr0, flagsRegCR1 cr1) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
- effect(USE_KILL needle, /* TDEF needle, */ TEMP result,
+ effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11084,7 +11199,7 @@
iRegIdst tmp1, iRegIdst tmp2, iRegIdst tmp3, iRegIdst tmp4, iRegIdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecntImm)));
- effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP result,
+ effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
// Required for EA: check if it is still a type_array.
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
@@ -11118,7 +11233,7 @@
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6) %{
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary needle needlecnt)));
effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
- TEMP result,
+ TEMP_DEF result,
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported.
ins_cost(300);
@@ -11142,7 +11257,7 @@
iRegPdst tmp1, iRegPdst tmp2,
flagsRegCR0 cr0, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cntImm));
- effect(TEMP result, TEMP tmp1, TEMP tmp2,
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
KILL cr0, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(250);
@@ -11165,7 +11280,7 @@
iRegPdst tmp1, iRegPdst tmp2, iRegPdst tmp3, iRegPdst tmp4, iRegPdst tmp5,
flagsRegCR0 cr0, flagsRegCR1 cr1, flagsRegCR6 cr6, regCTR ctr) %{
match(Set result (StrEquals (Binary str1 str2) cnt));
- effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
+ effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
KILL cr0, KILL cr1, KILL cr6, KILL ctr);
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
ins_cost(300);
@@ -11188,7 +11303,7 @@
instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
- effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP result, TEMP tmp, KILL cr0, KILL ctr);
+ effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
ins_cost(300);
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
--- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -483,15 +483,6 @@
}
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->is_a(BarrierSet::G1SATBCTLogging),
- "Must be if we're using this.");
- return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1374,6 +1374,7 @@
}
void InterpreterMacroAssembler::test_invocation_counter_for_mdp(Register invocation_count,
+ Register method_counters,
Register Rtmp,
Label &profile_continue) {
assert(ProfileInterpreter, "must be profiling interpreter");
@@ -1386,9 +1387,8 @@
br_notnull_short(ImethodDataPtr, Assembler::pn, done);
// Test to see if we should create a method data oop
- AddressLiteral profile_limit((address) &InvocationCounter::InterpreterProfileLimit);
- sethi(profile_limit, Rtmp);
- ld(Rtmp, profile_limit.low10(), Rtmp);
+ Address profile_limit(method_counters, MethodCounters::interpreter_profile_limit_offset());
+ ld(profile_limit, Rtmp);
cmp(invocation_count, Rtmp);
// Use long branches because call_VM() code and following code generated by
// test_backedge_count_for_osr() is large in debug VM.
@@ -2375,6 +2375,7 @@
#ifndef CC_INTERP
void InterpreterMacroAssembler::test_backedge_count_for_osr( Register backedge_count,
+ Register method_counters,
Register branch_bcp,
Register Rtmp ) {
Label did_not_overflow;
@@ -2382,8 +2383,8 @@
assert_different_registers(backedge_count, Rtmp, branch_bcp);
assert(UseOnStackReplacement,"Must UseOnStackReplacement to test_backedge_count_for_osr");
- AddressLiteral limit(&InvocationCounter::InterpreterBackwardBranchLimit);
- load_contents(limit, Rtmp);
+ Address limit(method_counters, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset()));
+ ld(limit, Rtmp);
cmp_and_br_short(backedge_count, Rtmp, Assembler::lessUnsigned, Assembler::pt, did_not_overflow);
// When ProfileInterpreter is on, the backedge_count comes from the
@@ -2500,17 +2501,13 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where) {
ld(counter_addr, scratch1);
add(scratch1, increment, scratch1);
- if (is_simm13(mask)) {
- andcc(scratch1, mask, G0);
- } else {
- set(mask, scratch2);
- andcc(scratch1, scratch2, G0);
- }
+ ld(mask_addr, scratch2);
+ andcc(scratch1, scratch2, G0);
br(cond, false, Assembler::pn, *where);
delayed()->st(scratch1, counter_addr);
}
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -267,7 +267,7 @@
void increment_invocation_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
void increment_backedge_counter( Register Rcounters, Register Rtmp, Register Rtmp2 );
#ifndef CC_INTERP
- void test_backedge_count_for_osr( Register backedge_count, Register branch_bcp, Register Rtmp );
+ void test_backedge_count_for_osr(Register backedge_count, Register method_counters, Register branch_bcp, Register Rtmp );
#endif /* CC_INTERP */
// Object locking
@@ -280,7 +280,7 @@
void set_method_data_pointer_for_bcp();
void test_method_data_pointer(Label& zero_continue);
void verify_method_data_pointer();
- void test_invocation_counter_for_mdp(Register invocation_count, Register Rtmp, Label &profile_continue);
+ void test_invocation_counter_for_mdp(Register invocation_count, Register method_counters, Register Rtmp, Label &profile_continue);
void set_mdp_data_at(int constant, Register value);
void increment_mdp_data_at(Address counter, Register bumped_count,
@@ -291,7 +291,7 @@
Register bumped_count, Register scratch2,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask_addr,
Register scratch1, Register scratch2,
Condition cond, Label *where);
void set_mdp_flag_at(int flag_constant, Register scratch);
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
//
-// Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
//
// This code is free software; you can redistribute it and/or modify it
@@ -2996,7 +2996,7 @@
%}
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
- Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone;
+ Label Lchar, Lchar_loop, Ldone;
MacroAssembler _masm(&cbuf);
Register str1_reg = reg_to_register_object($str1$$reg);
--- a/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/templateInterpreter_sparc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -282,12 +282,11 @@
void InterpreterGenerator::generate_counter_incr(Label* overflow, Label* profile_method, Label* profile_method_continue) {
// Note: In tiered we increment either counters in MethodCounters* or in
// MDO depending if we're profiling or not.
- const Register Rcounters = G3_scratch;
+ const Register G3_method_counters = G3_scratch;
Label done;
if (TieredCompilation) {
const int increment = InvocationCounter::count_increment;
- const int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
@@ -297,6 +296,7 @@
Address mdo_invocation_counter(G4_scratch,
in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G4_scratch, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask,
G3_scratch, Lscratch,
Assembler::zero, overflow);
@@ -305,20 +305,21 @@
// Increment counter in MethodCounters*
__ bind(no_mdo);
- Address invocation_counter(Rcounters,
+ Address invocation_counter(G3_method_counters,
in_bytes(MethodCounters::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
- __ get_method_counters(Lmethod, Rcounters, done);
+ __ get_method_counters(Lmethod, G3_method_counters, done);
+ Address mask(G3_method_counters, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
G4_scratch, Lscratch,
Assembler::zero, overflow);
__ bind(done);
- } else {
+ } else { // not TieredCompilation
// Update standard invocation counters
- __ get_method_counters(Lmethod, Rcounters, done);
- __ increment_invocation_counter(Rcounters, O0, G4_scratch);
+ __ get_method_counters(Lmethod, G3_method_counters, done);
+ __ increment_invocation_counter(G3_method_counters, O0, G4_scratch);
if (ProfileInterpreter) {
- Address interpreter_invocation_counter(Rcounters,
+ Address interpreter_invocation_counter(G3_method_counters,
in_bytes(MethodCounters::interpreter_invocation_counter_offset()));
__ ld(interpreter_invocation_counter, G4_scratch);
__ inc(G4_scratch);
@@ -327,16 +328,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- AddressLiteral profile_limit((address)&InvocationCounter::InterpreterProfileLimit);
- __ load_contents(profile_limit, G3_scratch);
- __ cmp_and_br_short(O0, G3_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
+ Address profile_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_profile_limit_offset()));
+ __ ld(profile_limit, G1_scratch);
+ __ cmp_and_br_short(O0, G1_scratch, Assembler::lessUnsigned, Assembler::pn, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(*profile_method);
}
- AddressLiteral invocation_limit((address)&InvocationCounter::InterpreterInvocationLimit);
- __ load_contents(invocation_limit, G3_scratch);
+ Address invocation_limit(G3_method_counters, in_bytes(MethodCounters::interpreter_invocation_limit_offset()));
+ __ ld(invocation_limit, G3_scratch);
__ cmp(O0, G3_scratch);
__ br(Assembler::greaterEqualUnsigned, false, Assembler::pn, *overflow); // Far distance
__ delayed()->nop();
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1599,13 +1599,12 @@
// Bump bytecode pointer by displacement (take the branch)
__ delayed()->add( O1_disp, Lbcp, Lbcp ); // add to bc addr
- const Register Rcounters = G3_scratch;
- __ get_method_counters(Lmethod, Rcounters, Lforward);
+ const Register G3_method_counters = G3_scratch;
+ __ get_method_counters(Lmethod, G3_method_counters, Lforward);
if (TieredCompilation) {
Label Lno_mdo, Loverflow;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// If no method data exists, go to profile_continue.
__ ld_ptr(Lmethod, Method::method_data_offset(), G4_scratch);
@@ -1614,6 +1613,7 @@
// Increment backedge counter in the MDO
Address mdo_backedge_counter(G4_scratch, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G4_scratch, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask, G3_scratch, O0,
Assembler::notZero, &Lforward);
__ ba_short(Loverflow);
@@ -1621,9 +1621,10 @@
// If there's no MDO, increment counter in MethodCounters*
__ bind(Lno_mdo);
- Address backedge_counter(Rcounters,
+ Address backedge_counter(G3_method_counters,
in_bytes(MethodCounters::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ Address mask(G3_method_counters, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(backedge_counter, increment, mask, G4_scratch, O0,
Assembler::notZero, &Lforward);
__ bind(Loverflow);
@@ -1663,18 +1664,19 @@
__ jmp(O2, G0);
__ delayed()->nop();
- } else {
+ } else { // not TieredCompilation
// Update Backedge branch separately from invocations
const Register G4_invoke_ctr = G4;
- __ increment_backedge_counter(Rcounters, G4_invoke_ctr, G1_scratch);
+ __ increment_backedge_counter(G3_method_counters, G4_invoke_ctr, G1_scratch);
if (ProfileInterpreter) {
- __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_scratch, Lforward);
+ __ test_invocation_counter_for_mdp(G4_invoke_ctr, G3_method_counters, G1_scratch, Lforward);
if (UseOnStackReplacement) {
- __ test_backedge_count_for_osr(O2_bumped_count, l_cur_bcp, G3_scratch);
+
+ __ test_backedge_count_for_osr(O2_bumped_count, G3_method_counters, l_cur_bcp, G1_scratch);
}
} else {
if (UseOnStackReplacement) {
- __ test_backedge_count_for_osr(G4_invoke_ctr, l_cur_bcp, G3_scratch);
+ __ test_backedge_count_for_osr(G4_invoke_ctr, G3_method_counters, l_cur_bcp, G1_scratch);
}
}
}
--- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -541,15 +541,6 @@
}
-jbyte* G1PostBarrierStub::_byte_map_base = NULL;
-
-jbyte* G1PostBarrierStub::byte_map_base_slow() {
- BarrierSet* bs = Universe::heap()->barrier_set();
- assert(bs->is_a(BarrierSet::G1SATBCTLogging),
- "Must be if we're using this.");
- return ((G1SATBCardTableModRefBS*)bs)->byte_map_base;
-}
-
void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
__ bind(_entry);
assert(addr()->is_register(), "Precondition.");
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1360,7 +1360,7 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -182,7 +182,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1426,7 +1426,7 @@
// Jump if ((*counter_addr += increment) & mask) satisfies the condition.
void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where) {
if (!preloaded) {
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -191,7 +191,7 @@
void increment_mdp_data_at(Register mdp_in, Register reg, int constant,
bool decrement = false);
void increment_mask_and_jump(Address counter_addr,
- int increment, int mask,
+ int increment, Address mask,
Register scratch, bool preloaded,
Condition cond, Label* where);
void set_mdp_flag_at(Register mdp_in, int flag_constant);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -6194,7 +6194,7 @@
ShortBranchVerifier sbv(this);
assert(UseSSE42Intrinsics, "SSE4.2 is required");
- // This method uses pcmpestri inxtruction with bound registers
+ // This method uses pcmpestri instruction with bound registers
// inputs:
// xmm - substring
// rax - substring length (elements count)
@@ -6355,7 +6355,7 @@
//
assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0");
- // This method uses pcmpestri inxtruction with bound registers
+ // This method uses pcmpestri instruction with bound registers
// inputs:
// xmm - substring
// rax - substring length (elements count)
@@ -6644,7 +6644,6 @@
// start from first character again because it has aligned address.
int stride2 = 16;
int adr_stride = stride << scale;
- int adr_stride2 = stride2 << scale;
assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri");
// rax and rdx are used by pcmpestri as elements counters
@@ -6743,7 +6742,7 @@
// inputs:
// vec1- substring
// rax - negative string length (elements count)
- // mem - scaned string
+ // mem - scanned string
// rdx - string length (elements count)
// pcmpmask - cmp mode: 11000 (string compare with negated result)
// + 00 (unsigned bytes) or + 01 (unsigned shorts)
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_32.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -346,7 +346,6 @@
// depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@@ -356,6 +355,7 @@
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@@ -366,11 +366,12 @@
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
+ const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask,
rcx, false, Assembler::zero, overflow);
__ bind(done);
- } else {
- const Address backedge_counter (rax,
+ } else { // not TieredCompilation
+ const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
const Address invocation_counter(rax,
@@ -400,16 +401,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- __ cmp32(rcx,
- ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
- __ cmp32(rcx,
- ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
--- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86_64.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -299,7 +299,6 @@
// Note: In tiered we increment either counters in Method* or in MDO depending if we're profiling or not.
if (TieredCompilation) {
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0InvokeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
Label no_mdo;
if (ProfileInterpreter) {
// Are we profiling?
@@ -309,6 +308,7 @@
// Increment counter in the MDO
const Address mdo_invocation_counter(rax, in_bytes(MethodData::invocation_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rax, in_bytes(MethodData::invoke_mask_offset()));
__ increment_mask_and_jump(mdo_invocation_counter, increment, mask, rcx, false, Assembler::zero, overflow);
__ jmp(done);
}
@@ -318,10 +318,11 @@
MethodCounters::invocation_counter_offset() +
InvocationCounter::counter_offset());
__ get_method_counters(rbx, rax, done);
+ const Address mask(rax, in_bytes(MethodCounters::invoke_mask_offset()));
__ increment_mask_and_jump(invocation_counter, increment, mask, rcx,
false, Assembler::zero, overflow);
__ bind(done);
- } else {
+ } else { // not TieredCompilation
const Address backedge_counter(rax,
MethodCounters::backedge_counter_offset() +
InvocationCounter::counter_offset());
@@ -350,14 +351,16 @@
if (ProfileInterpreter && profile_method != NULL) {
// Test to see if we should create a method data oop
- __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterProfileLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, *profile_method_continue);
// if no method data exists, go to profile_method
__ test_method_data_pointer(rax, *profile_method);
}
- __ cmp32(rcx, ExternalAddress((address)&InvocationCounter::InterpreterInvocationLimit));
+ __ movptr(rax, Address(rbx, Method::method_counters_offset()));
+ __ cmp32(rcx, Address(rax, in_bytes(MethodCounters::interpreter_invocation_limit_offset())));
__ jcc(Assembler::aboveEqual, *overflow);
__ bind(done);
}
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1621,7 +1621,6 @@
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1630,6 +1629,7 @@
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@@ -1637,9 +1637,10 @@
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+ const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
- } else {
+ } else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@@ -1653,8 +1654,7 @@
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@@ -1662,8 +1662,7 @@
if (UseOnStackReplacement) {
// check for overflow against rbx, which is the MDO taken count
- __ cmp32(rbx,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes from the
@@ -1678,8 +1677,7 @@
} else {
if (UseOnStackReplacement) {
// check for overflow against rax, which is the sum of the counters
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1642,7 +1642,6 @@
if (TieredCompilation) {
Label no_mdo;
int increment = InvocationCounter::count_increment;
- int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
if (ProfileInterpreter) {
// Are we profiling?
__ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
@@ -1651,6 +1650,7 @@
// Increment the MDO backedge counter
const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
in_bytes(InvocationCounter::counter_offset()));
+ const Address mask(rbx, in_bytes(MethodData::backedge_mask_offset()));
__ increment_mask_and_jump(mdo_backedge_counter, increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
__ jmp(dispatch);
@@ -1658,9 +1658,10 @@
__ bind(no_mdo);
// Increment backedge counter in MethodCounters*
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
+ const Address mask(rcx, in_bytes(MethodCounters::backedge_mask_offset()));
__ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
rax, false, Assembler::zero, &backedge_counter_overflow);
- } else {
+ } else { // not TieredCompilation
// increment counter
__ movptr(rcx, Address(rcx, Method::method_counters_offset()));
__ movl(rax, Address(rcx, be_offset)); // load backedge counter
@@ -1674,8 +1675,7 @@
if (ProfileInterpreter) {
// Test to see if we should create a method data oop
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_profile_limit_offset())));
__ jcc(Assembler::less, dispatch);
// if no method data exists, go to profile method
@@ -1683,8 +1683,7 @@
if (UseOnStackReplacement) {
// check for overflow against ebx which is the MDO taken count
- __ cmp32(rbx,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rbx, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::below, dispatch);
// When ProfileInterpreter is on, the backedge_count comes
@@ -1702,8 +1701,7 @@
if (UseOnStackReplacement) {
// check for overflow against eax, which is the sum of the
// counters
- __ cmp32(rax,
- ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
+ __ cmp32(rax, Address(rcx, in_bytes(MethodCounters::interpreter_backward_branch_limit_offset())));
__ jcc(Assembler::aboveEqual, backedge_counter_overflow);
}
--- a/hotspot/src/os/aix/vm/os_aix.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/aix/vm/os_aix.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright 2012, 2014 SAP AG. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -1115,6 +1115,15 @@
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
+void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ assert(status != -1, "aix error at gettimeofday()");
+ seconds = jlong(time.tv_sec);
+ nanos = jlong(time.tv_usec) * 1000;
+}
+
+
// We need to manually declare mread_real_time,
// because IBM didn't provide a prototype in time.h.
// (they probably only ever tested in C, not C++)
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -31,6 +31,7 @@
#include "os_aix.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/perfMemory.hpp"
+#include "services/memTracker.hpp"
#include "utilities/exceptions.hpp"
// put OS-includes here
@@ -196,12 +197,37 @@
return pid;
}
+// Check if the given statbuf is considered a secure directory for
+// the backing store files. Returns true if the directory is considered
+// a secure location. Returns false if the statbuf is a symbolic link or
+// if an error occurred.
+static bool is_statbuf_secure(struct stat *statp) {
+ if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
+ // The path represents a link or some non-directory file type,
+ // which is not what we expected. Declare it insecure.
+ //
+ return false;
+ }
+ // We have an existing directory, check if the permissions are safe.
+ if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
+ // The directory is open for writing and could be subjected
+ // to a symlink or a hard link attack. Declare it insecure.
+ return false;
+ }
+ // See if the uid of the directory matches the effective uid of the process.
+ //
+ if (statp->st_uid != geteuid()) {
+ // The directory was not created by this user, declare it insecure.
+ return false;
+ }
+ return true;
+}
-// check if the given path is considered a secure directory for
+
+// Check if the given path is considered a secure directory for
// the backing store files. Returns true if the directory exists
// and is considered a secure location. Returns false if the path
// is a symbolic link or if an error occurred.
-//
static bool is_directory_secure(const char* path) {
struct stat statbuf;
int result = 0;
@@ -211,38 +237,276 @@
return false;
}
- // the path exists, now check it's mode
- if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) {
- // the path represents a link or some non-directory file type,
- // which is not what we expected. declare it insecure.
- //
+ // The path exists, see if it is secure.
+ return is_statbuf_secure(&statbuf);
+}
+
+// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.)
+// Check if the given directory file descriptor is considered a secure
+// directory for the backing store files. Returns true if the directory
+// exists and is considered a secure location. Returns false if the path
+// is a symbolic link or if an error occurred.
+static bool is_dirfd_secure(int dir_fd) {
+ struct stat statbuf;
+ int result = 0;
+
+ RESTARTABLE(::fstat(dir_fd, &statbuf), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ // The path exists, now check its mode.
+ return is_statbuf_secure(&statbuf);
+}
+
+
+// Check to make sure fd1 and fd2 are referencing the same file system object.
+static bool is_same_fsobject(int fd1, int fd2) {
+ struct stat statbuf1;
+ struct stat statbuf2;
+ int result = 0;
+
+ RESTARTABLE(::fstat(fd1, &statbuf1), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+ RESTARTABLE(::fstat(fd2, &statbuf2), result);
+ if (result == OS_ERR) {
+ return false;
+ }
+
+ if ((statbuf1.st_ino == statbuf2.st_ino) &&
+ (statbuf1.st_dev == statbuf2.st_dev)) {
+ return true;
+ } else {
return false;
}
- else {
- // we have an existing directory, check if the permissions are safe.
- //
- if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) {
- // the directory is open for writing and could be subjected
- // to a symlnk attack. declare it insecure.
- //
- return false;
+}
+
+// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1.
+// We use the jdk6 implementation here.
+#ifndef O_NOFOLLOW
+// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour
+// was done in jdk 5/6 hotspot by Oracle this way
+static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) {
+ struct stat orig_st;
+ struct stat new_st;
+ bool create;
+ int error;
+ int fd;
+
+ create = false;
+
+ if (lstat(path, &orig_st) != 0) {
+ if (errno == ENOENT && (oflag & O_CREAT) != 0) {
+ // File doesn't exist, but_we want to create it, add O_EXCL flag
+ // to make sure no-one creates it (or a symlink) before us
+ // This works as we expect with symlinks, from posix man page:
+ // 'If O_EXCL and O_CREAT are set, and path names a symbolic
+ // link, open() shall fail and set errno to [EEXIST]'.
+ oflag |= O_EXCL;
+ create = true;
+ } else {
+ // File doesn't exist, and we are not creating it.
+ return OS_ERR;
+ }
+ } else {
+ // Lstat success, check if existing file is a link.
+ if ((orig_st.st_mode & S_IFMT) == S_IFLNK) {
+ // File is a symlink.
+ errno = ELOOP;
+ return OS_ERR;
+ }
+ }
+
+ if (use_mode == true) {
+ fd = open(path, oflag, mode);
+ } else {
+ fd = open(path, oflag);
+ }
+
+ if (fd == OS_ERR) {
+ return fd;
+ }
+
+ // Can't do inode checks on before/after if we created the file.
+ if (create == false) {
+ if (fstat(fd, &new_st) != 0) {
+ // Keep errno from fstat, in case close also fails.
+ error = errno;
+ ::close(fd);
+ errno = error;
+ return OS_ERR;
+ }
+
+ if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) {
+ // File was tampered with during race window.
+ ::close(fd);
+ errno = EEXIST;
+ if (PrintMiscellaneous && Verbose) {
+ warning("possible file tampering attempt detected when opening %s", path);
+ }
+ return OS_ERR;
}
}
+
+ return fd;
+}
+
+static int open_o_nofollow(const char* path, int oflag, mode_t mode) {
+ return open_o_nofollow_impl(path, oflag, mode, true);
+}
+
+static int open_o_nofollow(const char* path, int oflag) {
+ return open_o_nofollow_impl(path, oflag, 0, false);
+}
+#endif
+
+// Open the directory of the given path and validate it.
+// Return a DIR * of the open directory.
+static DIR *open_directory_secure(const char* dirname) {
+ // Open the directory using open() so that it can be verified
+ // to be secure by calling is_dirfd_secure(), opendir() and then check
+ // to see if they are the same file system object. This method does not
+ // introduce a window of opportunity for the directory to be attacked that
+ // calling opendir() and is_directory_secure() does.
+ int result;
+ DIR *dirp = NULL;
+
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+ // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+ RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result);
+#else
+ // workaround (jdk6 coding)
+ RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result);
+#endif
+
+ if (result == OS_ERR) {
+ // Directory doesn't exist or is a symlink, so there is nothing to cleanup.
+ if (PrintMiscellaneous && Verbose) {
+ if (errno == ELOOP) {
+ warning("directory %s is a symlink and is not secure\n", dirname);
+ } else {
+ warning("could not open directory %s: %s\n", dirname, strerror(errno));
+ }
+ }
+ return dirp;
+ }
+ int fd = result;
+
+ // Determine if the open directory is secure.
+ if (!is_dirfd_secure(fd)) {
+ // The directory is not a secure directory.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Open the directory.
+ dirp = ::opendir(dirname);
+ if (dirp == NULL) {
+ // The directory doesn't exist, close fd and return.
+ os::close(fd);
+ return dirp;
+ }
+
+ // Check to make sure fd and dirp are referencing the same file system object.
+ if (!is_same_fsobject(fd, dirp->dd_fd)) {
+ // The directory is not secure.
+ os::close(fd);
+ os::closedir(dirp);
+ dirp = NULL;
+ return dirp;
+ }
+
+ // Close initial open now that we know directory is secure
+ os::close(fd);
+
+ return dirp;
+}
+
+// NOTE: The code below uses fchdir(), open() and unlink() because
+// fdopendir(), openat() and unlinkat() are not supported on all
+// versions. Once the support for fdopendir(), openat() and unlinkat()
+// is available on all supported versions the code can be changed
+// to use these functions.
+
+// Open the directory of the given path, validate it and set the
+// current working directory to it.
+// Return a DIR * of the open directory and the saved cwd fd.
+//
+static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) {
+
+ // Open the directory.
+ DIR* dirp = open_directory_secure(dirname);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
+ return dirp;
+ }
+ int fd = dirp->dd_fd;
+
+ // Open a fd to the cwd and save it off.
+ int result;
+ RESTARTABLE(::open(".", O_RDONLY), result);
+ if (result == OS_ERR) {
+ *saved_cwd_fd = -1;
+ } else {
+ *saved_cwd_fd = result;
+ }
+
+ // Set the current directory to dirname by using the fd of the directory.
+ result = fchdir(fd);
+
+ return dirp;
+}
+
+// Close the directory and restore the current working directory.
+static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) {
+
+ int result;
+ // If we have a saved cwd change back to it and close the fd.
+ if (saved_cwd_fd != -1) {
+ result = fchdir(saved_cwd_fd);
+ ::close(saved_cwd_fd);
+ }
+
+ // Close the directory.
+ os::closedir(dirp);
+}
+
+// Check if the given file descriptor is considered a secure.
+static bool is_file_secure(int fd, const char *filename) {
+
+ int result;
+ struct stat statbuf;
+
+ // Determine if the file is secure.
+ RESTARTABLE(::fstat(fd, &statbuf), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("fstat failed on %s: %s\n", filename, strerror(errno));
+ }
+ return false;
+ }
+ if (statbuf.st_nlink > 1) {
+ // A file with multiple links is not expected.
+ if (PrintMiscellaneous && Verbose) {
+ warning("file %s has multiple links\n", filename);
+ }
+ return false;
+ }
return true;
}
-
-// return the user name for the given user id
+// Return the user name for the given user id.
//
-// the caller is expected to free the allocated memory.
-//
+// The caller is expected to free the allocated memory.
static char* get_user_name(uid_t uid) {
struct passwd pwent;
- // determine the max pwbuf size from sysconf, and hardcode
+ // Determine the max pwbuf size from sysconf, and hardcode
// a default if this not available through sysconf.
- //
long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == -1)
bufsize = 1024;
@@ -344,7 +608,8 @@
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
- DIR* subdirp = os::opendir(usrdir_name);
+ // Open the user directory.
+ DIR* subdirp = open_directory_secure(usrdir_name);
if (subdirp == NULL) {
FREE_C_HEAP_ARRAY(char, usrdir_name);
@@ -464,28 +729,7 @@
}
}
-
-// remove file
-//
-// this method removes the file with the given file name in the
-// named directory.
-//
-static void remove_file(const char* dirname, const char* filename) {
-
- size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
-
- strcpy(path, dirname);
- strcat(path, "/");
- strcat(path, filename);
-
- remove_file(path);
-
- FREE_C_HEAP_ARRAY(char, path);
-}
-
-
-// cleanup stale shared memory resources
+// Cleanup stale shared memory resources
//
// This method attempts to remove all stale shared memory files in
// the named user temporary directory. It scans the named directory
@@ -493,33 +737,26 @@
// process id is extracted from the file name and a test is run to
// determine if the process is alive. If the process is not alive,
// any stale file resources are removed.
-//
static void cleanup_sharedmem_resources(const char* dirname) {
- // open the user temp directory
- DIR* dirp = os::opendir(dirname);
-
+ int saved_cwd_fd;
+ // Open the directory.
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
if (dirp == NULL) {
- // directory doesn't exist, so there is nothing to cleanup
+ // Directory doesn't exist or is insecure, so there is nothing to cleanup.
return;
}
- if (!is_directory_secure(dirname)) {
- // the directory is not a secure directory
- os::closedir(dirp);
- return;
- }
-
- // for each entry in the directory that matches the expected file
+ // For each entry in the directory that matches the expected file
// name pattern, determine if the file resources are stale and if
// so, remove the file resources. Note, instrumented HotSpot processes
// for this user may start and/or terminate during this search and
// remove or create new files in this directory. The behavior of this
// loop under these conditions is dependent upon the implementation of
// opendir/readdir.
- //
struct dirent* entry;
char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
+
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -529,56 +766,55 @@
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
- // attempt to remove all unexpected files, except "." and ".."
- remove_file(dirname, entry->d_name);
+ // Attempt to remove all unexpected files, except "." and "..".
+ unlink(entry->d_name);
}
errno = 0;
continue;
}
- // we now have a file name that converts to a valid integer
+ // We now have a file name that converts to a valid integer
// that could represent a process id . if this process id
// matches the current process id or the process is not running,
// then remove the stale file resources.
//
- // process liveness is detected by sending signal number 0 to
+ // Process liveness is detected by sending signal number 0 to
// the process id (see kill(2)). if kill determines that the
// process does not exist, then the file resources are removed.
// if kill determines that that we don't have permission to
// signal the process, then the file resources are assumed to
// be stale and are removed because the resources for such a
// process should be in a different user specific directory.
- //
if ((pid == os::current_process_id()) ||
(kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) {
- remove_file(dirname, entry->d_name);
+ unlink(entry->d_name);
}
errno = 0;
}
- os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf);
+
+ // Close the directory and reset the current working directory.
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
-// make the user specific temporary directory. Returns true if
+// Make the user specific temporary directory. Returns true if
// the directory exists and is secure upon return. Returns false
// if the directory exists but is either a symlink, is otherwise
// insecure, or if an error occurred.
-//
static bool make_user_tmp_dir(const char* dirname) {
- // create the directory with 0755 permissions. note that the directory
+ // Create the directory with 0755 permissions. note that the directory
// will be owned by euid::egid, which may not be the same as uid::gid.
- //
if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) {
if (errno == EEXIST) {
// The directory already exists and was probably created by another
// JVM instance. However, this could also be the result of a
// deliberate symlink. Verify that the existing directory is safe.
- //
if (!is_directory_secure(dirname)) {
- // directory is not secure
+ // Directory is not secure.
if (PrintMiscellaneous && Verbose) {
warning("%s directory is insecure\n", dirname);
}
@@ -614,19 +850,63 @@
return -1;
}
+ int saved_cwd_fd;
+ // Open the directory and set the current working directory to it.
+ DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd);
+ if (dirp == NULL) {
+ // Directory doesn't exist or is insecure, so cannot create shared
+ // memory file.
+ return -1;
+ }
+
+ // Open the filename in the current directory.
+ // Cannot use O_TRUNC here; truncation of an existing file has to happen
+ // after the is_file_secure() check below.
int result;
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+ // so provide a workaround in this case.
+#ifdef O_NOFOLLOW
+ RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result);
+#else
+ // workaround function (jdk6 code)
+ RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result);
+#endif
+
if (result == OS_ERR) {
if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
+ if (errno == ELOOP) {
+ warning("file %s is a symlink and is not secure\n", filename);
+ } else {
+ warning("could not create file %s: %s\n", filename, strerror(errno));
+ }
}
+ // Close the directory and reset the current working directory.
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
+
return -1;
}
+ // Close the directory and reset the current working directory.
+ close_directory_secure_cwd(dirp, saved_cwd_fd);
// save the file descriptor
int fd = result;
+ // Check to see if the file is secure.
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ // Truncate the file to get rid of any existing data.
+ RESTARTABLE(::ftruncate(fd, (off_t)0), result);
+ if (result == OS_ERR) {
+ if (PrintMiscellaneous && Verbose) {
+ warning("could not truncate shared memory file: %s\n", strerror(errno));
+ }
+ ::close(fd);
+ return -1;
+ }
// set the file size
RESTARTABLE(::ftruncate(fd, (off_t)size), result);
if (result == OS_ERR) {
@@ -648,7 +928,14 @@
// open the file
int result;
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open;
+ // so provide a workaround in this case
+#ifdef O_NOFOLLOW
RESTARTABLE(::open(filename, oflags), result);
+#else
+ RESTARTABLE(::open_o_nofollow(filename, oflags), result);
+#endif
+
if (result == OS_ERR) {
if (errno == ENOENT) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -662,8 +949,15 @@
THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno));
}
}
+ int fd = result;
- return result;
+ // Check to see if the file is secure.
+ if (!is_file_secure(fd, filename)) {
+ ::close(fd);
+ return -1;
+ }
+
+ return fd;
}
// create a named shared memory region. returns the address of the
@@ -695,13 +989,21 @@
char* dirname = get_user_tmp_dir(user_name);
char* filename = get_sharedmem_filename(dirname, vmid);
+ // Get the short filename.
+ char* short_filename = strrchr(filename, '/');
+ if (short_filename == NULL) {
+ short_filename = filename;
+ } else {
+ short_filename++;
+ }
+
// cleanup any stale shared memory files
cleanup_sharedmem_resources(dirname);
assert(((size > 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemory region size");
- fd = create_sharedmem_resources(dirname, filename, size);
+ fd = create_sharedmem_resources(dirname, short_filename, size);
FREE_C_HEAP_ARRAY(char, user_name);
FREE_C_HEAP_ARRAY(char, dirname);
@@ -733,6 +1035,9 @@
// clear the shared memory region
(void)::memset((void*) mapAddress, 0, size);
+ // It does not go through os api, the operation has to record from here.
+ MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
return mapAddress;
}
@@ -807,7 +1112,7 @@
char* mapAddress;
int result;
int fd;
- size_t size;
+ size_t size = 0;
const char* luser = NULL;
int mmap_prot;
@@ -819,12 +1124,18 @@
// constructs for the file and the shared memory mapping.
if (mode == PerfMemory::PERF_MODE_RO) {
mmap_prot = PROT_READ;
+
+ // No O_NOFOLLOW defined at buildtime, and it is not documented for open.
+#ifdef O_NOFOLLOW
+ file_flags = O_RDONLY | O_NOFOLLOW;
+#else
file_flags = O_RDONLY;
+#endif
}
else if (mode == PerfMemory::PERF_MODE_RW) {
#ifdef LATER
mmap_prot = PROT_READ | PROT_WRITE;
- file_flags = O_RDWR;
+ file_flags = O_RDWR | O_NOFOLLOW;
#else
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unsupported access mode");
@@ -853,9 +1164,9 @@
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (luser != user) {
- FREE_C_HEAP_ARRAY(char, luser);
+ FREE_C_HEAP_ARRAY(char, luser, mtInternal);
}
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
@@ -901,6 +1212,9 @@
"Could not map PerfMemory");
}
+ // It does not go through os api, the operation has to record from here.
+ MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal);
+
*addr = mapAddress;
*sizep = size;
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -984,6 +984,14 @@
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
+void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ assert(status != -1, "bsd error");
+ seconds = jlong(time.tv_sec);
+ nanos = jlong(time.tv_usec) * 1000;
+}
+
#ifndef __APPLE__
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)
--- a/hotspot/src/os/linux/vm/os_linux.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1322,6 +1322,15 @@
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
}
+void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
+ timeval time;
+ int status = gettimeofday(&time, NULL);
+ assert(status != -1, "linux error");
+ seconds = jlong(time.tv_sec);
+ nanos = jlong(time.tv_usec) * 1000;
+}
+
+
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)
#endif
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1475,6 +1475,16 @@
return jlong(t.tv_sec) * 1000 + jlong(t.tv_usec) / 1000;
}
+void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
+ timeval t;
+ if (gettimeofday(&t, NULL) == -1) {
+ fatal(err_msg("os::javaTimeSystemUTC: gettimeofday (%s)", strerror(errno)));
+ }
+ seconds = jlong(t.tv_sec);
+ nanos = jlong(t.tv_usec) * 1000;
+}
+
+
jlong os::javaTimeNanos() {
return (jlong)getTimeNanos();
}
--- a/hotspot/src/os/windows/vm/os_windows.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -428,9 +428,9 @@
}
// Diagnostic code to investigate JDK-6573254
- int res = 50115; // non-java thread
+ int res = 30115; // non-java thread
if (thread->is_Java_thread()) {
- res = 40115; // java thread
+ res = 20115; // java thread
}
// Install a win32 structured exception handler around every thread created
@@ -839,6 +839,12 @@
return (a - offset()) / 10000;
}
+// Returns time ticks in (10th of micro seconds)
+jlong windows_to_time_ticks(FILETIME wt) {
+ jlong a = jlong_from(wt.dwHighDateTime, wt.dwLowDateTime);
+ return (a - offset());
+}
+
FILETIME java_to_windows_time(jlong l) {
jlong a = (l * 10000) + offset();
FILETIME result;
@@ -874,6 +880,15 @@
}
}
+void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
+ FILETIME wt;
+ GetSystemTimeAsFileTime(&wt);
+ jlong ticks = windows_to_time_ticks(wt); // 10th of micros
+ jlong secs = jlong(ticks / 10000000); // 10000 * 1000
+ seconds = secs;
+ nanos = jlong(ticks - (secs*10000000)) * 100;
+}
+
jlong os::javaTimeNanos() {
if (!win32::_has_performance_count) {
return javaTimeMillis() * NANOSECS_PER_MILLISEC; // the best we can do.
@@ -1693,7 +1708,7 @@
}
break;
- case 6004:
+ case 10000:
if (is_workstation) {
st->print("10");
} else {
@@ -3791,6 +3806,7 @@
static INIT_ONCE init_once_crit_sect = INIT_ONCE_STATIC_INIT;
static CRITICAL_SECTION crit_sect;
+ static volatile jint process_exiting = 0;
int i, j;
DWORD res;
HANDLE hproc, hthr;
@@ -3798,10 +3814,10 @@
// The first thread that reached this point, initializes the critical section.
if (!InitOnceExecuteOnce(&init_once_crit_sect, init_crit_sect_call, &crit_sect, NULL)) {
warning("crit_sect initialization failed in %s: %d\n", __FILE__, __LINE__);
- } else {
+ } else if (OrderAccess::load_acquire(&process_exiting) == 0) {
EnterCriticalSection(&crit_sect);
- if (what == EPT_THREAD) {
+ if (what == EPT_THREAD && OrderAccess::load_acquire(&process_exiting) == 0) {
// Remove from the array those handles of the threads that have completed exiting.
for (i = 0, j = 0; i < handle_count; ++i) {
res = WaitForSingleObject(handles[i], 0 /* don't wait */);
@@ -3856,7 +3872,7 @@
// The current exiting thread has stored its handle in the array, and now
// should leave the critical section before calling _endthreadex().
- } else { // what != EPT_THREAD
+ } else if (what != EPT_THREAD) {
if (handle_count > 0) {
// Before ending the process, make sure all the threads that had called
// _endthreadex() completed.
@@ -3882,24 +3898,28 @@
handle_count = 0;
}
- // End the process, not leaving critical section.
- // This makes sure no other thread executes exit-related code at the same
- // time, thus a race is avoided.
- if (what == EPT_PROCESS) {
- ::exit(exit_code);
- } else {
- _exit(exit_code);
- }
+ OrderAccess::release_store(&process_exiting, 1);
}
LeaveCriticalSection(&crit_sect);
}
+
+ if (what == EPT_THREAD) {
+ while (OrderAccess::load_acquire(&process_exiting) != 0) {
+ // Some other thread is about to call exit(), so we
+ // don't let the current thread proceed to _endthreadex()
+ SuspendThread(GetCurrentThread());
+ // Avoid busy-wait loop, if SuspendThread() failed.
+ Sleep(EXIT_TIMEOUT);
+ }
+ }
}
// We are here if either
// - there's no 'race at exit' bug on this OS release;
// - initialization of the critical section failed (unlikely);
- // - the current thread has stored its handle and left the critical section.
+ // - the current thread has stored its handle and left the critical section;
+ // - the process-exiting thread has raised the flag and left the critical section.
if (what == EPT_THREAD) {
_endthreadex((unsigned)exit_code);
} else if (what == EPT_PROCESS) {
--- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -601,15 +601,6 @@
LIR_Opr _addr;
LIR_Opr _new_val;
- static jbyte* _byte_map_base;
- static jbyte* byte_map_base_slow();
- static jbyte* byte_map_base() {
- if (_byte_map_base == NULL) {
- _byte_map_base = byte_map_base_slow();
- }
- return _byte_map_base;
- }
-
public:
// addr (the address of the object head) and new_val must be registers.
G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -32,6 +32,7 @@
#include "ci/ciArrayKlass.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciObjArray.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vm_version.hpp"
@@ -3351,7 +3352,12 @@
if (!x->inlinee()->is_accessor()) {
CodeEmitInfo* info = state_for(x, x->state(), true);
// Notify the runtime very infrequently only to take care of counter overflows
- increment_event_counter_impl(info, x->inlinee(), (1 << Tier23InlineeNotifyFreqLog) - 1, InvocationEntryBci, false, true);
+ int freq_log = Tier23InlineeNotifyFreqLog;
+ double scale;
+ if (_method->has_option_value("CompileThresholdScaling", scale)) {
+ freq_log = Arguments::scaled_freq_log(freq_log, scale);
+ }
+ increment_event_counter_impl(info, x->inlinee(), right_n_bits(freq_log), InvocationEntryBci, false, true);
}
}
@@ -3366,7 +3372,11 @@
ShouldNotReachHere();
}
// Increment the appropriate invocation/backedge counter and notify the runtime.
- increment_event_counter_impl(info, info->scope()->method(), (1 << freq_log) - 1, bci, backedge, true);
+ double scale;
+ if (_method->has_option_value("CompileThresholdScaling", scale)) {
+ freq_log = Arguments::scaled_freq_log(freq_log, scale);
+ }
+ increment_event_counter_impl(info, info->scope()->method(), right_n_bits(freq_log), bci, backedge, true);
}
void LIRGenerator::decrement_age(CodeEmitInfo* info) {
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -221,6 +221,30 @@
return (const char*)end;
}
+template <class T, class N> void CompactHashtable<T, N>::symbols_do(SymbolClosure *cl) {
+ assert(!DumpSharedSpaces, "run-time only");
+ for (juint i = 0; i < _bucket_count; i ++) {
+ juint bucket_info = _buckets[i];
+ juint bucket_offset = BUCKET_OFFSET(bucket_info);
+ int bucket_type = BUCKET_TYPE(bucket_info);
+ juint* bucket = _buckets + bucket_offset;
+ juint* bucket_end = _buckets;
+
+ Symbol* sym;
+ if (bucket_type == COMPACT_BUCKET_TYPE) {
+ sym = (Symbol*)((void*)(_base_address + bucket[0]));
+ cl->do_symbol(&sym);
+ } else {
+ bucket_end += BUCKET_OFFSET(_buckets[i + 1]);
+ while (bucket < bucket_end) {
+ sym = (Symbol*)((void*)(_base_address + bucket[1]));
+ cl->do_symbol(&sym);
+ bucket += 2;
+ }
+ }
+ }
+}
+
// Explicitly instantiate these types
template class CompactHashtable<Symbol*, char>;
--- a/hotspot/src/share/vm/classfile/compactHashtable.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/classfile/compactHashtable.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -249,6 +249,9 @@
}
return NULL;
}
+
+ // iterate over symbols
+ void symbols_do(SymbolClosure *cl);
};
////////////////////////////////////////////////////////////////////////
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,6 +82,10 @@
// Call function for all symbols in the symbol table.
void SymbolTable::symbols_do(SymbolClosure *cl) {
+ // all symbols from shared table
+ _shared_table.symbols_do(cl);
+
+ // all symbols from the dynamic table
const int n = the_table()->table_size();
for (int i = 0; i < n; i++) {
for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
--- a/hotspot/src/share/vm/classfile/verifier.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1546,10 +1546,15 @@
no_control_flow = true; break;
case Bytecodes::_getstatic :
case Bytecodes::_putstatic :
+ // pass TRUE, operand can be an array type for getstatic/putstatic.
+ verify_field_instructions(
+ &bcs, ¤t_frame, cp, true, CHECK_VERIFY(this));
+ no_control_flow = false; break;
case Bytecodes::_getfield :
case Bytecodes::_putfield :
+ // pass FALSE, operand can't be an array type for getfield/putfield.
verify_field_instructions(
- &bcs, ¤t_frame, cp, CHECK_VERIFY(this));
+ &bcs, ¤t_frame, cp, false, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_invokevirtual :
case Bytecodes::_invokespecial :
@@ -1945,7 +1950,7 @@
InstanceKlass* target_instance = InstanceKlass::cast(target_class);
fieldDescriptor fd;
if (is_method) {
- Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::normal);
+ Method* m = target_instance->uncached_lookup_method(field_name, field_sig, Klass::find_overpass);
if (m != NULL && m->is_protected()) {
if (!this_class->is_same_class_package(m->method_holder())) {
return true;
@@ -2107,6 +2112,7 @@
void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs,
StackMapFrame* current_frame,
constantPoolHandle cp,
+ bool allow_arrays,
TRAPS) {
u2 index = bcs->get_index_u2();
verify_cp_type(bcs->bci(), index, cp,
@@ -2126,8 +2132,8 @@
// Get referenced class type
VerificationType ref_class_type = cp_ref_index_to_type(
index, cp, CHECK_VERIFY(this));
- if (!ref_class_type.is_object()) {
- /* Unreachable? Class file parser verifies Fieldref contents */
+ if (!ref_class_type.is_object() &&
+ (!allow_arrays || !ref_class_type.is_array())) {
verify_error(ErrorContext::bad_type(bcs->bci(),
TypeOrigin::cp(index, ref_class_type)),
"Expecting reference to class in class %s at constant pool index %d",
@@ -2490,7 +2496,7 @@
Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method(
vmSymbols::object_initializer_name(),
cp->signature_ref_at(bcs->get_index_u2()),
- Klass::normal);
+ Klass::find_overpass);
// Do nothing if method is not found. Let resolution detect the error.
if (m != NULL) {
instanceKlassHandle mh(THREAD, m->method_holder());
--- a/hotspot/src/share/vm/classfile/verifier.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/classfile/verifier.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -297,7 +297,7 @@
void verify_field_instructions(
RawBytecodeStream* bcs, StackMapFrame* current_frame,
- constantPoolHandle cp, TRAPS);
+ constantPoolHandle cp, bool allow_arrays, TRAPS);
void verify_invoke_init(
RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,
--- a/hotspot/src/share/vm/code/codeCache.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/code/codeCache.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -199,15 +199,10 @@
}
guarantee(NonProfiledCodeHeapSize + ProfiledCodeHeapSize + NonNMethodCodeHeapSize <= ReservedCodeCacheSize, "Size check");
- // Align reserved sizes of CodeHeaps
- size_t non_method_size = ReservedCodeSpace::allocation_align_size_up(NonNMethodCodeHeapSize);
- size_t profiled_size = ReservedCodeSpace::allocation_align_size_up(ProfiledCodeHeapSize);
- size_t non_profiled_size = ReservedCodeSpace::allocation_align_size_up(NonProfiledCodeHeapSize);
-
- // Compute initial sizes of CodeHeaps
- size_t init_non_method_size = MIN2(InitialCodeCacheSize, non_method_size);
- size_t init_profiled_size = MIN2(InitialCodeCacheSize, profiled_size);
- size_t init_non_profiled_size = MIN2(InitialCodeCacheSize, non_profiled_size);
+ // Align CodeHeaps
+ size_t alignment = heap_alignment();
+ size_t non_method_size = align_size_up(NonNMethodCodeHeapSize, alignment);
+ size_t profiled_size = align_size_down(ProfiledCodeHeapSize, alignment);
// Reserve one continuous chunk of memory for CodeHeaps and split it into
// parts for the individual heaps. The memory layout looks like this:
@@ -216,25 +211,34 @@
// Profiled nmethods
// Non-nmethods
// ---------- low ------------
- ReservedCodeSpace rs = reserve_heap_memory(non_profiled_size + profiled_size + non_method_size);
+ ReservedCodeSpace rs = reserve_heap_memory(ReservedCodeCacheSize);
ReservedSpace non_method_space = rs.first_part(non_method_size);
ReservedSpace rest = rs.last_part(non_method_size);
ReservedSpace profiled_space = rest.first_part(profiled_size);
ReservedSpace non_profiled_space = rest.last_part(profiled_size);
// Non-nmethods (stubs, adapters, ...)
- add_heap(non_method_space, "CodeHeap 'non-nmethods'", init_non_method_size, CodeBlobType::NonNMethod);
+ add_heap(non_method_space, "CodeHeap 'non-nmethods'", CodeBlobType::NonNMethod);
// Tier 2 and tier 3 (profiled) methods
- add_heap(profiled_space, "CodeHeap 'profiled nmethods'", init_profiled_size, CodeBlobType::MethodProfiled);
+ add_heap(profiled_space, "CodeHeap 'profiled nmethods'", CodeBlobType::MethodProfiled);
// Tier 1 and tier 4 (non-profiled) methods and native methods
- add_heap(non_profiled_space, "CodeHeap 'non-profiled nmethods'", init_non_profiled_size, CodeBlobType::MethodNonProfiled);
+ add_heap(non_profiled_space, "CodeHeap 'non-profiled nmethods'", CodeBlobType::MethodNonProfiled);
+}
+
+size_t CodeCache::heap_alignment() {
+ // If large page support is enabled, align code heaps according to large
+ // page size to make sure that code cache is covered by large pages.
+ const size_t page_size = os::can_execute_large_page_memory() ?
+ os::page_size_for_region_unaligned(ReservedCodeCacheSize, 8) :
+ os::vm_page_size();
+ return MAX2(page_size, (size_t) os::vm_allocation_granularity());
}
ReservedCodeSpace CodeCache::reserve_heap_memory(size_t size) {
// Determine alignment
const size_t page_size = os::can_execute_large_page_memory() ?
- MIN2(os::page_size_for_region(InitialCodeCacheSize, 8),
- os::page_size_for_region(size, 8)) :
+ MIN2(os::page_size_for_region_aligned(InitialCodeCacheSize, 8),
+ os::page_size_for_region_aligned(size, 8)) :
os::vm_page_size();
const size_t granularity = os::vm_allocation_granularity();
const size_t r_align = MAX2(page_size, granularity);
@@ -284,7 +288,7 @@
return NULL;
}
-void CodeCache::add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type) {
+void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) {
// Check if heap is needed
if (!heap_available(code_blob_type)) {
return;
@@ -295,8 +299,8 @@
_heaps->append(heap);
// Reserve Space
+ size_t size_initial = MIN2(InitialCodeCacheSize, rs.size());
size_initial = round_to(size_initial, os::vm_page_size());
-
if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) {
vm_exit_during_initialization("Could not reserve enough space for code cache");
}
@@ -840,7 +844,7 @@
} else {
// Use a single code heap
ReservedCodeSpace rs = reserve_heap_memory(ReservedCodeCacheSize);
- add_heap(rs, "CodeCache", InitialCodeCacheSize, CodeBlobType::All);
+ add_heap(rs, "CodeCache", CodeBlobType::All);
}
// Initialize ICache flush mechanism
--- a/hotspot/src/share/vm/code/codeCache.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/code/codeCache.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -98,12 +98,13 @@
// CodeHeap management
static void initialize_heaps(); // Initializes the CodeHeaps
// Creates a new heap with the given name and size, containing CodeBlobs of the given type
- static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type);
+ static void add_heap(ReservedSpace rs, const char* name, int code_blob_type);
static CodeHeap* get_code_heap(const CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob
static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType
// Returns the name of the VM option to set the size of the corresponding CodeHeap
static const char* get_code_heap_flag_name(int code_blob_type);
static bool heap_available(int code_blob_type); // Returns true if an own CodeHeap for the given CodeBlobType is available
+ static size_t heap_alignment(); // Returns the alignment of the CodeHeaps in bytes
static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps
// Iteration
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1470,7 +1470,9 @@
// The method may be explicitly excluded by the user.
bool quietly;
- if (CompilerOracle::should_exclude(method, quietly)) {
+ double scale;
+ if (CompilerOracle::should_exclude(method, quietly)
+ || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
if (!quietly) {
// This does not happen quietly...
ResourceMark rm;
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -553,7 +553,8 @@
int match = MethodMatcher::Exact;
while (name[0] == '*') {
match |= MethodMatcher::Suffix;
- strcpy(name, name + 1);
+ // Copy remaining string plus NUL to the beginning
+ memmove(name, name + 1, strlen(name + 1) + 1);
}
if (strcmp(name, "*") == 0) return MethodMatcher::Any;
@@ -689,6 +690,13 @@
return NULL;
}
+int skip_whitespace(char* line) {
+ // Skip any leading spaces
+ int whitespace_read = 0;
+ sscanf(line, "%*[ \t]%n", &whitespace_read);
+ return whitespace_read;
+}
+
void CompilerOracle::parse_from_line(char* line) {
if (line[0] == '\0') return;
if (line[0] == '#') return;
@@ -755,15 +763,9 @@
line += bytes_read;
- // Skip any leading spaces before signature
- int whitespace_read = 0;
- sscanf(line, "%*[ \t]%n", &whitespace_read);
- if (whitespace_read > 0) {
- line += whitespace_read;
- }
-
// there might be a signature following the method.
// signatures always begin with ( so match that by hand
+ line += skip_whitespace(line);
if (1 == sscanf(line, "(%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) {
sig[0] = '(';
line += bytes_read;
@@ -786,7 +788,9 @@
//
// For future extensions: extend scan_flag_and_value()
char option[256]; // stores flag for Type (1) and type of Type (2)
- while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
+
+ line += skip_whitespace(line);
+ while (sscanf(line, "%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) {
if (match != NULL && !_quiet) {
// Print out the last match added
ttyLocker ttyl;
@@ -816,6 +820,7 @@
// Type (1) option
match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true);
}
+ line += skip_whitespace(line);
} // while(
} else {
match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -162,8 +162,8 @@
"we should have already filtered out humongous regions");
assert(_end == orig_end(),
"we should have already filtered out humongous regions");
-
- _in_collection_set = false;
+ assert(!_in_collection_set,
+ err_msg("Should not clear heap region %u in the collection set", hrm_index()));
set_allocation_context(AllocationContext::system());
set_young_index_in_cset(-1);
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1194,8 +1194,10 @@
return real_forwardee(old);
}
- new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
- old, m, sz);
+ if (!_promotion_failed) {
+ new_obj = _next_gen->par_promote(par_scan_state->thread_num(),
+ old, m, sz);
+ }
if (new_obj == NULL) {
// promotion failed, forward to self
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -61,9 +61,9 @@
void GenerationSizer::initialize_size_info() {
trace_gen_sizes("ps heap raw");
- const size_t max_page_sz = os::page_size_for_region(_max_heap_byte_size, 8);
+ const size_t max_page_sz = os::page_size_for_region_aligned(_max_heap_byte_size, 8);
const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old
- const size_t min_page_sz = os::page_size_for_region(_min_heap_byte_size, min_pages);
+ const size_t min_page_sz = os::page_size_for_region_aligned(_min_heap_byte_size, min_pages);
const size_t page_sz = MIN2(max_page_sz, min_page_sz);
// Can a page size be something else than a power of two?
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -41,7 +41,7 @@
const size_t words = bits / BitsPerWord;
const size_t raw_bytes = words * sizeof(idx_t);
- const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -403,7 +403,7 @@
ParallelCompactData::create_vspace(size_t count, size_t element_size)
{
const size_t raw_bytes = count * element_size;
- const size_t page_sz = os::page_size_for_region(raw_bytes, 10);
+ const size_t page_sz = os::page_size_for_region_aligned(raw_bytes, 10);
const size_t granularity = os::vm_allocation_granularity();
_reserved_byte_size = align_size_up(raw_bytes, MAX2(page_sz, granularity));
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -53,7 +53,7 @@
/*
* USELABELS - If using GCC, then use labels for the opcode dispatching
* rather -then a switch statement. This improves performance because it
- * gives us the oportunity to have the instructions that calculate the
+ * gives us the opportunity to have the instructions that calculate the
* next opcode to jump to be intermixed with the rest of the instructions
* that implement the opcode (see UPDATE_PC_AND_TOS_AND_CONTINUE macro).
*/
--- a/hotspot/src/share/vm/interpreter/invocationCounter.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/interpreter/invocationCounter.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -36,7 +36,7 @@
// Implementation notes: For space reasons, state & counter are both encoded in one word,
// The state is encoded using some of the least significant bits, the counter is using the
// more significant bits. The counter is incremented before a method is activated and an
-// action is triggered when when count() > limit().
+// action is triggered when count() > limit().
class InvocationCounter VALUE_OBJ_CLASS_SPEC {
friend class VMStructs;
@@ -48,7 +48,6 @@
number_of_state_bits = 2,
number_of_carry_bits = 1,
number_of_noncount_bits = number_of_state_bits + number_of_carry_bits,
- number_of_count_bits = BitsPerInt - number_of_noncount_bits,
state_limit = nth_bit(number_of_state_bits),
count_grain = nth_bit(number_of_state_bits + number_of_carry_bits),
carry_mask = right_n_bits(number_of_carry_bits) << number_of_state_bits,
@@ -68,6 +67,7 @@
count_increment = count_grain, // use this value to increment the 32bit _counter word
count_mask_value = count_mask, // use this value to mask the backedge counter
count_shift = number_of_noncount_bits,
+ number_of_count_bits = BitsPerInt - number_of_noncount_bits,
count_limit = nth_bit(number_of_count_bits - 1)
};
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -289,11 +289,11 @@
// returns first instance method
// Looks up method in classes, then looks up local default methods
void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) {
- Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::normal);
+ Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::find_overpass);
result = methodHandle(THREAD, result_oop);
while (!result.is_null() && result->is_static() && result->method_holder()->super() != NULL) {
KlassHandle super_klass = KlassHandle(THREAD, result->method_holder()->super());
- result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal));
+ result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::find_overpass));
}
if (klass->oop_is_array()) {
@@ -320,7 +320,8 @@
// First check in default method array
if (!resolved_method->is_abstract() &&
(InstanceKlass::cast(klass())->default_methods() != NULL)) {
- int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature, false, false);
+ int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(),
+ name, signature, Klass::find_overpass, Klass::find_static);
if (index >= 0 ) {
vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index);
}
--- a/hotspot/src/share/vm/memory/heap.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/memory/heap.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -104,8 +104,8 @@
size_t page_size = os::vm_page_size();
if (os::can_execute_large_page_memory()) {
const size_t min_pages = 8;
- page_size = MIN2(os::page_size_for_region(committed_size, min_pages),
- os::page_size_for_region(rs.size(), min_pages));
+ page_size = MIN2(os::page_size_for_region_aligned(committed_size, min_pages),
+ os::page_size_for_region_aligned(rs.size(), min_pages));
}
const size_t granularity = os::vm_allocation_granularity();
--- a/hotspot/src/share/vm/memory/universe.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/memory/universe.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -115,6 +115,7 @@
LatestMethodCache* Universe::_finalizer_register_cache = NULL;
LatestMethodCache* Universe::_loader_addClass_cache = NULL;
LatestMethodCache* Universe::_pd_implies_cache = NULL;
+LatestMethodCache* Universe::_throw_illegal_access_error_cache = NULL;
oop Universe::_out_of_memory_error_java_heap = NULL;
oop Universe::_out_of_memory_error_metaspace = NULL;
oop Universe::_out_of_memory_error_class_metaspace = NULL;
@@ -130,7 +131,6 @@
oop Universe::_vm_exception = NULL;
oop Universe::_allocation_context_notification_obj = NULL;
-Method* Universe::_throw_illegal_access_error = NULL;
Array<int>* Universe::_the_empty_int_array = NULL;
Array<u2>* Universe::_the_empty_short_array = NULL;
Array<Klass*>* Universe::_the_empty_klass_array = NULL;
@@ -236,6 +236,7 @@
_finalizer_register_cache->serialize(f);
_loader_addClass_cache->serialize(f);
_pd_implies_cache->serialize(f);
+ _throw_illegal_access_error_cache->serialize(f);
}
void Universe::check_alignment(uintx size, uintx alignment, const char* name) {
@@ -664,6 +665,7 @@
Universe::_finalizer_register_cache = new LatestMethodCache();
Universe::_loader_addClass_cache = new LatestMethodCache();
Universe::_pd_implies_cache = new LatestMethodCache();
+ Universe::_throw_illegal_access_error_cache = new LatestMethodCache();
if (UseSharedSpaces) {
// Read the data structures supporting the shared spaces (shared
@@ -1016,7 +1018,8 @@
tty->print_cr("Unable to link/verify Unsafe.throwIllegalAccessError method");
return false; // initialization failed (cannot throw exception yet)
}
- Universe::_throw_illegal_access_error = m;
+ Universe::_throw_illegal_access_error_cache->init(
+ SystemDictionary::misc_Unsafe_klass(), m);
// Setup method for registering loaded classes in class loader vector
InstanceKlass::cast(SystemDictionary::ClassLoader_klass())->link_class(CHECK_false);
@@ -1042,7 +1045,7 @@
return false; // initialization failed
}
Universe::_pd_implies_cache->init(
- SystemDictionary::ProtectionDomain_klass(), m);;
+ SystemDictionary::ProtectionDomain_klass(), m);
}
// This needs to be done before the first scavenge/gc, since
--- a/hotspot/src/share/vm/memory/universe.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/memory/universe.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -148,8 +148,7 @@
static LatestMethodCache* _finalizer_register_cache; // static method for registering finalizable objects
static LatestMethodCache* _loader_addClass_cache; // method for registering loaded classes in class loader vector
static LatestMethodCache* _pd_implies_cache; // method for checking protection domain attributes
-
- static Method* _throw_illegal_access_error;
+ static LatestMethodCache* _throw_illegal_access_error_cache; // Unsafe.throwIllegalAccessError() method
// preallocated error objects (no backtrace)
static oop _out_of_memory_error_java_heap;
@@ -305,6 +304,7 @@
static Method* loader_addClass_method() { return _loader_addClass_cache->get_method(); }
static Method* protection_domain_implies_method() { return _pd_implies_cache->get_method(); }
+ static Method* throw_illegal_access_error() { return _throw_illegal_access_error_cache->get_method(); }
static oop null_ptr_exception_instance() { return _null_ptr_exception_instance; }
static oop arithmetic_exception_instance() { return _arithmetic_exception_instance; }
@@ -314,8 +314,6 @@
static inline oop allocation_context_notification_obj();
static inline void set_allocation_context_notification_obj(oop obj);
- static Method* throw_illegal_access_error() { return _throw_illegal_access_error; }
-
static Array<int>* the_empty_int_array() { return _the_empty_int_array; }
static Array<u2>* the_empty_short_array() { return _the_empty_short_array; }
static Array<Method*>* the_empty_method_array() { return _the_empty_method_array; }
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,10 +71,13 @@
return super()->find_field(name, sig, fd);
}
-Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
+Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const {
// There are no methods in an array klass but the super class (Object) has some
assert(super(), "super klass must be present");
- return super()->uncached_lookup_method(name, signature, mode);
+ // Always ignore overpass methods in superclasses, although technically the
+ // super klass of an array, (j.l.Object) should not have
+ // any overpass methods present.
+ return super()->uncached_lookup_method(name, signature, Klass::skip_overpass);
}
ArrayKlass::ArrayKlass(Symbol* name) {
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,7 +82,7 @@
Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const;
// Lookup operations
- Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
+ Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
// Casting from Klass*
static ArrayKlass* cast(Klass* k) {
--- a/hotspot/src/share/vm/oops/constantPool.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -493,12 +493,7 @@
}
char* ConstantPool::string_at_noresolve(int which) {
- Symbol* s = unresolved_string_at(which);
- if (s == NULL) {
- return (char*)"<pseudo-string>";
- } else {
- return unresolved_string_at(which)->as_C_string();
- }
+ return unresolved_string_at(which)->as_C_string();
}
BasicType ConstantPool::basic_type_for_signature_at(int which) {
@@ -1828,7 +1823,7 @@
// explicitly, because it may require scavenging.
int obj_index = cp_to_object_index(index);
pseudo_string_at_put(index, obj_index, patch());
- DEBUG_ONLY(cp_patches->at_put(index, Handle());)
+ DEBUG_ONLY(cp_patches->at_put(index, Handle());)
}
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/oops/constantPool.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/constantPool.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -48,17 +48,21 @@
class CPSlot VALUE_OBJ_CLASS_SPEC {
intptr_t _ptr;
public:
+ enum TagBits { _resolved_value = 0, _symbol_bit = 1, _pseudo_bit = 2, _symbol_mask = 3 };
+
CPSlot(intptr_t ptr): _ptr(ptr) {}
CPSlot(Klass* ptr): _ptr((intptr_t)ptr) {}
- CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | 1) {}
+ CPSlot(Symbol* ptr): _ptr((intptr_t)ptr | _symbol_bit) {}
+ CPSlot(Symbol* ptr, int tag_bits): _ptr((intptr_t)ptr | tag_bits) {}
intptr_t value() { return _ptr; }
- bool is_resolved() { return (_ptr & 1) == 0; }
- bool is_unresolved() { return (_ptr & 1) == 1; }
+ bool is_resolved() { return (_ptr & _symbol_bit ) == _resolved_value; }
+ bool is_unresolved() { return (_ptr & _symbol_bit ) != _resolved_value; }
+ bool is_pseudo_string() { return (_ptr & _symbol_mask) == _symbol_bit + _pseudo_bit; }
Symbol* get_symbol() {
assert(is_unresolved(), "bad call");
- return (Symbol*)(_ptr & ~1);
+ return (Symbol*)(_ptr & ~_symbol_mask);
}
Klass* get_klass() {
assert(is_resolved(), "bad call");
@@ -261,7 +265,7 @@
void unresolved_string_at_put(int which, Symbol* s) {
release_tag_at_put(which, JVM_CONSTANT_String);
- *symbol_at_addr(which) = s;
+ slot_at_put(which, CPSlot(s, CPSlot::_symbol_bit));
}
void int_at_put(int which, jint i) {
@@ -405,20 +409,18 @@
// use pseudo-strings to link themselves to related metaobjects.
bool is_pseudo_string_at(int which) {
- // A pseudo string is a string that doesn't have a symbol in the cpSlot
- return unresolved_string_at(which) == NULL;
+ assert(tag_at(which).is_string(), "Corrupted constant pool");
+ return slot_at(which).is_pseudo_string();
}
oop pseudo_string_at(int which, int obj_index) {
- assert(tag_at(which).is_string(), "Corrupted constant pool");
- assert(unresolved_string_at(which) == NULL, "shouldn't have symbol");
+ assert(is_pseudo_string_at(which), "must be a pseudo-string");
oop s = resolved_references()->obj_at(obj_index);
return s;
}
oop pseudo_string_at(int which) {
- assert(tag_at(which).is_string(), "Corrupted constant pool");
- assert(unresolved_string_at(which) == NULL, "shouldn't have symbol");
+ assert(is_pseudo_string_at(which), "must be a pseudo-string");
int obj_index = cp_to_object_index(which);
oop s = resolved_references()->obj_at(obj_index);
return s;
@@ -426,7 +428,8 @@
void pseudo_string_at_put(int which, int obj_index, oop x) {
assert(tag_at(which).is_string(), "Corrupted constant pool");
- unresolved_string_at_put(which, NULL); // indicates patched string
+ Symbol* sym = unresolved_string_at(which);
+ slot_at_put(which, CPSlot(sym, (CPSlot::_symbol_bit | CPSlot::_pseudo_bit)));
string_at_put(which, obj_index, x); // this works just fine
}
@@ -443,15 +446,14 @@
Symbol* unresolved_string_at(int which) {
assert(tag_at(which).is_string(), "Corrupted constant pool");
- Symbol* s = *symbol_at_addr(which);
- return s;
+ Symbol* sym = slot_at(which).get_symbol();
+ return sym;
}
// Returns an UTF8 for a CONSTANT_String entry at a given index.
// UTF8 char* representation was chosen to avoid conversion of
// java_lang_Strings at resolved entries into Symbol*s
// or vice versa.
- // Caller is responsible for checking for pseudo-strings.
char* string_at_noresolve(int which);
jint name_and_type_at(int which) {
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1416,18 +1416,21 @@
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(Symbol* name, Symbol* signature) const {
- return find_method_impl(name, signature, false);
+ return find_method_impl(name, signature, find_overpass, find_static);
}
-Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const {
- return InstanceKlass::find_method_impl(methods(), name, signature, skipping_overpass, false);
+Method* InstanceKlass::find_method_impl(Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const {
+ return InstanceKlass::find_method_impl(methods(), name, signature, overpass_mode, static_mode);
}
// find_instance_method looks up the name/signature in the local methods array
// and skips over static methods
Method* InstanceKlass::find_instance_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- Method* meth = InstanceKlass::find_method_impl(methods, name, signature, false, true);
+ Method* meth = InstanceKlass::find_method_impl(methods, name, signature,
+ find_overpass, skip_static);
+ assert(((meth == NULL) || !meth->is_static()), "find_instance_method should have skipped statics");
return meth;
}
@@ -1440,12 +1443,12 @@
// find_method looks up the name/signature in the local methods array
Method* InstanceKlass::find_method(
Array<Method*>* methods, Symbol* name, Symbol* signature) {
- return InstanceKlass::find_method_impl(methods, name, signature, false, false);
+ return InstanceKlass::find_method_impl(methods, name, signature, find_overpass, find_static);
}
Method* InstanceKlass::find_method_impl(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
- int hit = find_method_index(methods, name, signature, skipping_overpass, skipping_static);
+ Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
+ int hit = find_method_index(methods, name, signature, overpass_mode, static_mode);
return hit >= 0 ? methods->at(hit): NULL;
}
@@ -1463,7 +1466,9 @@
// is important during method resolution to prefer a static method, for example,
// over an overpass method.
int InstanceKlass::find_method_index(
- Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static) {
+ Array<Method*>* methods, Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode, StaticLookupMode static_mode) {
+ bool skipping_overpass = (overpass_mode == skip_overpass);
+ bool skipping_static = (static_mode == skip_static);
int hit = binary_search(methods, name);
if (hit != -1) {
Method* m = methods->at(hit);
@@ -1489,7 +1494,7 @@
}
// not found
#ifdef ASSERT
- int index = skipping_overpass || skipping_static ? -1 : linear_search(methods, name, signature);
+ int index = (skipping_overpass || skipping_static) ? -1 : linear_search(methods, name, signature);
assert(index == -1, err_msg("binary search should have found entry %d", index));
#endif
}
@@ -1515,16 +1520,16 @@
// uncached_lookup_method searches both the local class methods array and all
// superclasses methods arrays, skipping any overpass methods in superclasses.
-Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
- MethodLookupMode lookup_mode = mode;
+Method* InstanceKlass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const {
+ OverpassLookupMode overpass_local_mode = overpass_mode;
Klass* klass = const_cast<InstanceKlass*>(this);
while (klass != NULL) {
- Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, (lookup_mode == skip_overpass));
+ Method* method = InstanceKlass::cast(klass)->find_method_impl(name, signature, overpass_local_mode, find_static);
if (method != NULL) {
return method;
}
klass = InstanceKlass::cast(klass)->super();
- lookup_mode = skip_overpass; // Always ignore overpass methods in superclasses
+ overpass_local_mode = skip_overpass; // Always ignore overpass methods in superclasses
}
return NULL;
}
@@ -1554,7 +1559,7 @@
}
// Look up interfaces
if (m == NULL) {
- m = lookup_method_in_all_interfaces(name, signature, normal);
+ m = lookup_method_in_all_interfaces(name, signature, find_defaults);
}
return m;
}
@@ -1564,7 +1569,7 @@
// They should only be found in the initial InterfaceMethodRef
Method* InstanceKlass::lookup_method_in_all_interfaces(Symbol* name,
Symbol* signature,
- MethodLookupMode mode) const {
+ DefaultsLookupMode defaults_mode) const {
Array<Klass*>* all_ifs = transitive_interfaces();
int num_ifs = all_ifs->length();
InstanceKlass *ik = NULL;
@@ -1572,7 +1577,7 @@
ik = InstanceKlass::cast(all_ifs->at(i));
Method* m = ik->lookup_method(name, signature);
if (m != NULL && m->is_public() && !m->is_static() &&
- ((mode != skip_defaults) || !m->is_default_method())) {
+ ((defaults_mode != skip_defaults) || !m->is_default_method())) {
return m;
}
}
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -499,14 +499,15 @@
static bool method_matches(Method* m, Symbol* signature, bool skipping_overpass, bool skipping_static);
// find a local method index in default_methods (returns -1 if not found)
- static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
+ static int find_method_index(Array<Method*>* methods, Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
// lookup operation (returns NULL if not found)
- Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
+ Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
// lookup a method in all the interfaces that this class implements
// (returns NULL if not found)
- Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
+ Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, DefaultsLookupMode defaults_mode) const;
// lookup a method in local defaults then in all interfaces
// (returns NULL if not found)
@@ -1058,8 +1059,10 @@
Klass* array_klass_impl(bool or_null, TRAPS);
// find a local method (returns NULL if not found)
- Method* find_method_impl(Symbol* name, Symbol* signature, bool skipping_overpass) const;
- static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature, bool skipping_overpass, bool skipping_static);
+ Method* find_method_impl(Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode) const;
+ static Method* find_method_impl(Array<Method*>* methods, Symbol* name, Symbol* signature,
+ OverpassLookupMode overpass_mode, StaticLookupMode static_mode);
// Free CHeap allocated fields.
void release_C_heap_structures();
--- a/hotspot/src/share/vm/oops/klass.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/klass.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -140,7 +140,7 @@
return NULL;
}
-Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const {
+Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const {
#ifdef ASSERT
tty->print_cr("Error: uncached_lookup_method called on a klass oop."
" Likely error: reflection method does not correctly"
--- a/hotspot/src/share/vm/oops/klass.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/klass.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -164,7 +164,9 @@
void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw();
public:
- enum MethodLookupMode { normal, skip_overpass, skip_defaults };
+ enum DefaultsLookupMode { find_defaults, skip_defaults };
+ enum OverpassLookupMode { find_overpass, skip_overpass };
+ enum StaticLookupMode { find_static, skip_static };
bool is_klass() const volatile { return true; }
@@ -413,10 +415,10 @@
// lookup operation for MethodLookupCache
friend class MethodLookupCache;
virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const;
- virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const;
+ virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, OverpassLookupMode overpass_mode) const;
public:
Method* lookup_method(Symbol* name, Symbol* signature) const {
- return uncached_lookup_method(name, signature, normal);
+ return uncached_lookup_method(name, signature, find_overpass);
}
// array class with specific rank
--- a/hotspot/src/share/vm/oops/klassVtable.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/klassVtable.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -649,7 +649,7 @@
// this check for all access permissions.
InstanceKlass *sk = InstanceKlass::cast(super);
if (sk->has_miranda_methods()) {
- if (sk->lookup_method_in_all_interfaces(name, signature, Klass::normal) != NULL) {
+ if (sk->lookup_method_in_all_interfaces(name, signature, Klass::find_defaults) != NULL) {
return false; // found a matching miranda; we do not need a new entry
}
}
@@ -725,7 +725,7 @@
&& mo->method_holder() != NULL
&& mo->method_holder()->super() != NULL)
{
- mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::normal);
+ mo = mo->method_holder()->super()->uncached_lookup_method(name, signature, Klass::find_overpass);
}
if (mo == NULL || mo->access_flags().is_private() ) {
// super class hierarchy does not implement it or protection is different
@@ -770,7 +770,7 @@
if (is_miranda(im, class_methods, default_methods, super)) { // is it a miranda at all?
InstanceKlass *sk = InstanceKlass::cast(super);
// check if it is a duplicate of a super's miranda
- if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::normal) == NULL) {
+ if (sk->lookup_method_in_all_interfaces(im->name(), im->signature(), Klass::find_defaults) == NULL) {
new_mirandas->append(im);
}
if (all_mirandas != NULL) {
--- a/hotspot/src/share/vm/oops/method.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/method.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -412,15 +412,14 @@
}
methodHandle mh(m);
- ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
- MethodCounters* counters = MethodCounters::allocate(loader_data, THREAD);
+ MethodCounters* counters = MethodCounters::allocate(mh, THREAD);
if (HAS_PENDING_EXCEPTION) {
CompileBroker::log_metaspace_failure();
ClassLoaderDataGraph::set_metaspace_oom(true);
return NULL; // return the exception (which is cleared)
}
if (!mh->init_method_counters(counters)) {
- MetadataFactory::free_metadata(loader_data, counters);
+ MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
}
return mh->method_counters();
}
--- a/hotspot/src/share/vm/oops/methodCounters.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/methodCounters.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -23,10 +23,11 @@
*/
#include "precompiled.hpp"
#include "oops/methodCounters.hpp"
-#include "runtime/thread.inline.hpp"
+#include "runtime/handles.inline.hpp"
-MethodCounters* MethodCounters::allocate(ClassLoaderData* loader_data, TRAPS) {
- return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters();
+MethodCounters* MethodCounters::allocate(methodHandle mh, TRAPS) {
+ ClassLoaderData* loader_data = mh->method_holder()->class_loader_data();
+ return new(loader_data, size(), false, MetaspaceObj::MethodCountersType, THREAD) MethodCounters(mh);
}
void MethodCounters::clear_counters() {
--- a/hotspot/src/share/vm/oops/methodCounters.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/methodCounters.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -26,7 +26,9 @@
#define SHARE_VM_OOPS_METHODCOUNTERS_HPP
#include "oops/metadata.hpp"
+#include "compiler/compilerOracle.hpp"
#include "interpreter/invocationCounter.hpp"
+#include "runtime/arguments.hpp"
class MethodCounters: public MetaspaceObj {
friend class VMStructs;
@@ -45,7 +47,11 @@
// 3. (INT_MIN..0] - method is hot and will deopt and get
// recompiled without the counters
int _nmethod_age;
-
+ int _interpreter_invocation_limit; // per-method InterpreterInvocationLimit
+ int _interpreter_backward_branch_limit; // per-method InterpreterBackwardBranchLimit
+ int _interpreter_profile_limit; // per-method InterpreterProfileLimit
+ int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
+ int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#ifdef TIERED
float _rate; // Events (invocation and backedge counter increments) per millisecond
jlong _prev_time; // Previous time the rate was acquired
@@ -53,15 +59,15 @@
u1 _highest_osr_comp_level; // Same for OSR level
#endif
- MethodCounters() : _interpreter_invocation_count(0),
- _interpreter_throwout_count(0),
- _number_of_breakpoints(0),
- _nmethod_age(INT_MAX)
+ MethodCounters(methodHandle mh) : _interpreter_invocation_count(0),
+ _interpreter_throwout_count(0),
+ _number_of_breakpoints(0),
+ _nmethod_age(INT_MAX)
#ifdef TIERED
- , _rate(0),
- _prev_time(0),
- _highest_comp_level(0),
- _highest_osr_comp_level(0)
+ , _rate(0),
+ _prev_time(0),
+ _highest_comp_level(0),
+ _highest_osr_comp_level(0)
#endif
{
invocation_counter()->init();
@@ -70,10 +76,28 @@
if (StressCodeAging) {
set_nmethod_age(HotMethodDetectionLimit);
}
+
+ // Set per-method thresholds.
+ double scale = 1.0;
+ CompilerOracle::has_option_value(mh, "CompileThresholdScaling", scale);
+
+ int compile_threshold = Arguments::scaled_compile_threshold(CompileThreshold, scale);
+ _interpreter_invocation_limit = compile_threshold << InvocationCounter::count_shift;
+ if (ProfileInterpreter) {
+ // If interpreter profiling is enabled, the backward branch limit
+ // is compared against the method data counter rather than an invocation
+ // counter, therefore no shifting of bits is required.
+ _interpreter_backward_branch_limit = (compile_threshold * (OnStackReplacePercentage - InterpreterProfilePercentage)) / 100;
+ } else {
+ _interpreter_backward_branch_limit = ((compile_threshold * OnStackReplacePercentage) / 100) << InvocationCounter::count_shift;
+ }
+ _interpreter_profile_limit = ((compile_threshold * InterpreterProfilePercentage) / 100) << InvocationCounter::count_shift;
+ _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+ _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
}
public:
- static MethodCounters* allocate(ClassLoaderData* loader_data, TRAPS);
+ static MethodCounters* allocate(methodHandle mh, TRAPS);
void deallocate_contents(ClassLoaderData* loader_data) {}
DEBUG_ONLY(bool on_stack() { return false; }) // for template
@@ -161,5 +185,24 @@
return offset_of(MethodCounters, _interpreter_invocation_count);
}
+ static ByteSize interpreter_invocation_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_invocation_limit);
+ }
+
+ static ByteSize interpreter_backward_branch_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_backward_branch_limit);
+ }
+
+ static ByteSize interpreter_profile_limit_offset() {
+ return byte_offset_of(MethodCounters, _interpreter_profile_limit);
+ }
+
+ static ByteSize invoke_mask_offset() {
+ return byte_offset_of(MethodCounters, _invoke_mask);
+ }
+
+ static ByteSize backedge_mask_offset() {
+ return byte_offset_of(MethodCounters, _backedge_mask);
+ }
};
#endif //SHARE_VM_OOPS_METHODCOUNTERS_HPP
--- a/hotspot/src/share/vm/oops/methodData.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/methodData.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -31,6 +31,7 @@
#include "memory/heapInspection.hpp"
#include "oops/methodData.hpp"
#include "prims/jvmtiRedefineClasses.hpp"
+#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/handles.inline.hpp"
@@ -1131,6 +1132,13 @@
_backedge_counter.init();
_invocation_counter_start = 0;
_backedge_counter_start = 0;
+
+ // Set per-method invoke- and backedge mask.
+ double scale = 1.0;
+ CompilerOracle::has_option_value(_method, "CompileThresholdScaling", scale);
+ _invoke_mask = right_n_bits(Arguments::scaled_freq_log(Tier0InvokeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+ _backedge_mask = right_n_bits(Arguments::scaled_freq_log(Tier0BackedgeNotifyFreqLog, scale)) << InvocationCounter::count_shift;
+
_tenure_traps = 0;
_num_loops = 0;
_num_blocks = 0;
--- a/hotspot/src/share/vm/oops/methodData.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/oops/methodData.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -2088,6 +2088,8 @@
int _invocation_counter_start;
int _backedge_counter_start;
uint _tenure_traps;
+ int _invoke_mask; // per-method Tier0InvokeNotifyFreqLog
+ int _backedge_mask; // per-method Tier0BackedgeNotifyFreqLog
#if INCLUDE_RTM_OPT
// State of RTM code generation during compilation of the method
@@ -2447,10 +2449,19 @@
static ByteSize invocation_counter_offset() {
return byte_offset_of(MethodData, _invocation_counter);
}
+
static ByteSize backedge_counter_offset() {
return byte_offset_of(MethodData, _backedge_counter);
}
+ static ByteSize invoke_mask_offset() {
+ return byte_offset_of(MethodData, _invoke_mask);
+ }
+
+ static ByteSize backedge_mask_offset() {
+ return byte_offset_of(MethodData, _backedge_mask);
+ }
+
static ByteSize parameters_type_data_di_offset() {
return byte_offset_of(MethodData, _parameters_type_data_di);
}
--- a/hotspot/src/share/vm/opto/chaitin.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/chaitin.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -582,6 +582,9 @@
// Peephole remove copies
post_allocate_copy_removal();
+ // Merge multidefs if multiple defs representing the same value are used in a single block.
+ merge_multidefs();
+
#ifdef ASSERT
// Veify the graph after RA.
verify(&live_arena);
--- a/hotspot/src/share/vm/opto/chaitin.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/chaitin.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -681,6 +681,32 @@
// Extend the node to LRG mapping
void add_reference( const Node *node, const Node *old_node);
+ // Record the first use of a def in the block for a register.
+ class RegDefUse {
+ Node* _def;
+ Node* _first_use;
+ public:
+ RegDefUse() : _def(NULL), _first_use(NULL) { }
+ Node* def() const { return _def; }
+ Node* first_use() const { return _first_use; }
+
+ void update(Node* def, Node* use) {
+ if (_def != def) {
+ _def = def;
+ _first_use = use;
+ }
+ }
+ void clear() {
+ _def = NULL;
+ _first_use = NULL;
+ }
+ };
+ typedef GrowableArray<RegDefUse> RegToDefUseMap;
+ int possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse);
+
+ // Merge nodes that are a part of a multidef lrg and produce the same value within a block.
+ void merge_multidefs();
+
private:
static int _final_loads, _final_stores, _final_copies, _final_memoves;
--- a/hotspot/src/share/vm/opto/doCall.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/doCall.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -94,7 +94,7 @@
if (log != NULL) {
int rid = (receiver_count >= 0)? log->identify(profile.receiver(0)): -1;
int r2id = (rid != -1 && profile.has_receiver(1))? log->identify(profile.receiver(1)):-1;
- log->begin_elem("call method='%d' count='%d' prof_factor='%g'",
+ log->begin_elem("call method='%d' count='%d' prof_factor='%f'",
log->identify(callee), site_count, prof_factor);
if (call_does_dispatch) log->print(" virtual='1'");
if (allow_inline) log->print(" inline='1'");
--- a/hotspot/src/share/vm/opto/escape.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/escape.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -2010,14 +2010,9 @@
bt = field->layout_type();
} else {
// Check for unsafe oop field access
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- int opcode = n->fast_out(i)->Opcode();
- if (opcode == Op_StoreP || opcode == Op_LoadP ||
- opcode == Op_StoreN || opcode == Op_LoadN) {
- bt = T_OBJECT;
- (*unsafe) = true;
- break;
- }
+ if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+ bt = T_OBJECT;
+ (*unsafe) = true;
}
}
} else if (adr_type->isa_aryptr()) {
@@ -2031,13 +2026,8 @@
}
} else if (adr_type->isa_rawptr() || adr_type->isa_klassptr()) {
// Allocation initialization, ThreadLocal field access, unsafe access
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- int opcode = n->fast_out(i)->Opcode();
- if (opcode == Op_StoreP || opcode == Op_LoadP ||
- opcode == Op_StoreN || opcode == Op_LoadN) {
- bt = T_OBJECT;
- break;
- }
+ if (n->has_out_with(Op_StoreP, Op_LoadP, Op_StoreN, Op_LoadN)) {
+ bt = T_OBJECT;
}
}
}
@@ -3092,13 +3082,7 @@
continue;
} else if (n->Opcode() == Op_EncodeISOArray) {
// get the memory projection
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node *use = n->fast_out(i);
- if (use->Opcode() == Op_SCMemProj) {
- n = use;
- break;
- }
- }
+ n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
} else {
assert(n->is_Mem(), "memory node required.");
@@ -3122,13 +3106,7 @@
continue; // don't push users
} else if (n->is_LoadStore()) {
// get the memory projection
- for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
- Node *use = n->fast_out(i);
- if (use->Opcode() == Op_SCMemProj) {
- n = use;
- break;
- }
- }
+ n = n->find_out_with(Op_SCMemProj);
assert(n->Opcode() == Op_SCMemProj, "memory projection required");
}
}
--- a/hotspot/src/share/vm/opto/ifg.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/ifg.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -535,12 +535,8 @@
// The method add_input_to_liveout() keeps such nodes alive (put them on liveout list)
// when it sees SCMemProj node in a block. Unfortunately SCMemProj node could be placed
// in block in such order that KILL MachProj nodes are processed first.
- uint cnt = def->outcnt();
- for (uint i = 0; i < cnt; i++) {
- Node* proj = def->raw_out(i);
- if (proj->Opcode() == Op_SCMemProj) {
- return false;
- }
+ if (def->has_out_with(Op_SCMemProj)) {
+ return false;
}
}
b->remove_node(location);
--- a/hotspot/src/share/vm/opto/library_call.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/library_call.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1351,7 +1351,6 @@
Node* cache = __ ConI(cache_i);
Node* md2 = __ ConI(md2_i);
Node* lastChar = __ ConI(target_array->char_at(target_length - 1));
- Node* targetCount = __ ConI(target_length);
Node* targetCountLess1 = __ ConI(target_length - 1);
Node* targetOffset = __ ConI(targetOffset_i);
Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1);
@@ -1408,8 +1407,6 @@
Node* arg = argument(1);
Node* result;
- // Disable the use of pcmpestri until it can be guaranteed that
- // the load doesn't cross into the uncommited space.
if (Matcher::has_match_rule(Op_StrIndexOf) &&
UseSSE42Intrinsics) {
// Generate SSE4.2 version of indexOf
@@ -1421,9 +1418,6 @@
return true;
}
- ciInstanceKlass* str_klass = env()->String_klass();
- const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(str_klass);
-
// Make the merge point
RegionNode* result_rgn = new RegionNode(4);
Node* result_phi = new PhiNode(result_rgn, TypeInt::INT);
--- a/hotspot/src/share/vm/opto/loopTransform.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -2057,10 +2057,9 @@
}
Node *main_cmp = main_bol->in(1);
if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
- _igvn.hash_delete(main_bol);
main_cmp = main_cmp->clone();// Clone a private CmpNode
register_new_node( main_cmp, main_cle->in(0) );
- main_bol->set_req(1,main_cmp);
+ _igvn.replace_input_of(main_bol, 1, main_cmp);
}
// Hack the now-private loop bounds
_igvn.replace_input_of(main_cmp, 2, main_limit);
--- a/hotspot/src/share/vm/opto/machnode.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/machnode.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -616,6 +616,29 @@
#endif
};
+// MachMergeNode is similar to a PhiNode in a sense it merges multiple values,
+// however it doesn't have a control input and is more like a MergeMem.
+// It is inserted after the register allocation is done to ensure that nodes use single
+// definition of a multidef lrg in a block.
+class MachMergeNode : public MachIdealNode {
+public:
+ MachMergeNode(Node *n1) {
+ init_class_id(Class_MachMerge);
+ add_req(NULL);
+ add_req(n1);
+ }
+ virtual const RegMask &out_RegMask() const { return in(1)->out_RegMask(); }
+ virtual const RegMask &in_RegMask(uint idx) const { return in(1)->in_RegMask(idx); }
+ virtual const class Type *bottom_type() const { return in(1)->bottom_type(); }
+ virtual uint ideal_reg() const { return bottom_type()->ideal_reg(); }
+ virtual uint oper_input_base() const { return 1; }
+ virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { }
+ virtual uint size(PhaseRegAlloc *ra_) const { return 0; }
+#ifndef PRODUCT
+ virtual const char *Name() const { return "MachMerge"; }
+#endif
+};
+
//------------------------------MachBranchNode--------------------------------
// Abstract machine branch Node
class MachBranchNode : public MachIdealNode {
--- a/hotspot/src/share/vm/opto/macro.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/macro.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -258,14 +258,7 @@
// Search for CastP2X->Xor->URShift->Cmp path which
// checks if the store done to a different from the value's region.
// And replace Cmp with #0 (false) to collapse G1 post barrier.
- Node* xorx = NULL;
- for (DUIterator_Fast imax, i = p2x->fast_outs(imax); i < imax; i++) {
- Node* u = p2x->fast_out(i);
- if (u->Opcode() == Op_XorX) {
- xorx = u;
- break;
- }
- }
+ Node* xorx = p2x->find_out_with(Op_XorX);
assert(xorx != NULL, "missing G1 post barrier");
Node* shift = xorx->unique_out();
Node* cmpx = shift->unique_out();
--- a/hotspot/src/share/vm/opto/memnode.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/memnode.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -2609,7 +2609,6 @@
return false; // if not a distinct instance, there may be aliases of the address
for (DUIterator_Fast imax, i = adr->fast_outs(imax); i < imax; i++) {
Node *use = adr->fast_out(i);
- int opc = use->Opcode();
if (use->is_Load() || use->is_LoadStore()) {
return false;
}
--- a/hotspot/src/share/vm/opto/node.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/node.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -881,6 +881,34 @@
return (Node*) this;
}
+// Find out of current node that matches opcode.
+Node* Node::find_out_with(int opcode) {
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ Node* use = fast_out(i);
+ if (use->Opcode() == opcode) {
+ return use;
+ }
+ }
+ return NULL;
+}
+
+// Return true if the current node has an out that matches opcode.
+bool Node::has_out_with(int opcode) {
+ return (find_out_with(opcode) != NULL);
+}
+
+// Return true if the current node has an out that matches any of the opcodes.
+bool Node::has_out_with(int opcode1, int opcode2, int opcode3, int opcode4) {
+ for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
+ int opcode = fast_out(i)->Opcode();
+ if (opcode == opcode1 || opcode == opcode2 || opcode == opcode3 || opcode == opcode4) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
//---------------------------uncast_helper-------------------------------------
Node* Node::uncast_helper(const Node* p) {
#ifdef ASSERT
--- a/hotspot/src/share/vm/opto/node.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/node.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -98,6 +98,7 @@
class MachSafePointNode;
class MachSpillCopyNode;
class MachTempNode;
+class MachMergeNode;
class Matcher;
class MemBarNode;
class MemBarStoreStoreNode;
@@ -436,6 +437,13 @@
return (this->uncast() == n->uncast());
}
+ // Find out of current node that matches opcode.
+ Node* find_out_with(int opcode);
+ // Return true if the current node has an out that matches opcode.
+ bool has_out_with(int opcode);
+ // Return true if the current node has an out that matches any of the opcodes.
+ bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
+
private:
static Node* uncast_helper(const Node* n);
@@ -507,18 +515,25 @@
//----------------- Other Node Properties
- // Generate class id for some ideal nodes to avoid virtual query
- // methods is_<Node>().
- // Class id is the set of bits corresponded to the node class and all its
- // super classes so that queries for super classes are also valid.
- // Subclasses of the same super class have different assigned bit
- // (the third parameter in the macro DEFINE_CLASS_ID).
- // Classes with deeper hierarchy are declared first.
- // Classes with the same hierarchy depth are sorted by usage frequency.
+ // Generate class IDs for (some) ideal nodes so that it is possible to determine
+ // the type of a node using a non-virtual method call (the method is_<Node>() below).
+ //
+ // A class ID of an ideal node is a set of bits. In a class ID, a single bit determines
+ // the type of the node the ID represents; another subset of an ID's bits are reserved
+ // for the superclasses of the node represented by the ID.
+ //
+ // By design, if A is a supertype of B, A.is_B() returns true and B.is_A()
+ // returns false. A.is_A() returns true.
//
- // The query method masks the bits to cut off bits of subclasses
- // and then compare the result with the class id
- // (see the macro DEFINE_CLASS_QUERY below).
+ // If two classes, A and B, have the same superclass, a different bit of A's class id
+ // is reserved for A's type than for B's type. That bit is specified by the third
+ // parameter in the macro DEFINE_CLASS_ID.
+ //
+ // By convention, classes with deeper hierarchy are declared first. Moreover,
+ // classes with the same hierarchy depth are sorted by usage frequency.
+ //
+ // The query method masks the bits to cut off bits of subclasses and then compares
+ // the result with the class id (see the macro DEFINE_CLASS_QUERY below).
//
// Class_MachCall=30, ClassMask_MachCall=31
// 12 8 4 0
@@ -592,6 +607,7 @@
DEFINE_CLASS_ID(MachTemp, Mach, 3)
DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
DEFINE_CLASS_ID(MachConstant, Mach, 5)
+ DEFINE_CLASS_ID(MachMerge, Mach, 6)
DEFINE_CLASS_ID(Type, Node, 2)
DEFINE_CLASS_ID(Phi, Type, 0)
@@ -763,6 +779,7 @@
DEFINE_CLASS_QUERY(MachSafePoint)
DEFINE_CLASS_QUERY(MachSpillCopy)
DEFINE_CLASS_QUERY(MachTemp)
+ DEFINE_CLASS_QUERY(MachMerge)
DEFINE_CLASS_QUERY(Mem)
DEFINE_CLASS_QUERY(MemBar)
DEFINE_CLASS_QUERY(MemBarStoreStore)
--- a/hotspot/src/share/vm/opto/output.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/output.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -2475,7 +2475,7 @@
if( iop == Op_Con ) continue; // Do not schedule Top
if( iop == Op_Node && // Do not schedule PhiNodes, ProjNodes
mach->pipeline() == MachNode::pipeline_class() &&
- !n->is_SpillCopy() ) // Breakpoints, Prolog, etc
+ !n->is_SpillCopy() && !n->is_MachMerge() ) // Breakpoints, Prolog, etc
continue;
break; // Funny loop structure to be sure...
}
--- a/hotspot/src/share/vm/opto/parse1.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/parse1.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -441,7 +441,7 @@
CompileLog* log = C->log();
if (log != NULL) {
- log->begin_head("parse method='%d' uses='%g'",
+ log->begin_head("parse method='%d' uses='%f'",
log->identify(parse_method), expected_uses);
if (depth() == 1 && C->is_osr_compilation()) {
log->print(" osr_bci='%d'", C->entry_bci());
--- a/hotspot/src/share/vm/opto/parse2.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/parse2.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -832,7 +832,7 @@
sprintf(prob_str_buf, "%g", prob);
prob_str = prob_str_buf;
}
- C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%g' prob='%s'",
+ C->log()->elem("branch target_bci='%d' taken='%d' not_taken='%d' cnt='%f' prob='%s'",
iter().get_dest(), taken, not_taken, cnt, prob_str);
}
return prob;
--- a/hotspot/src/share/vm/opto/phase.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/phase.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -110,6 +110,7 @@
tty->print_cr (" Compute Liveness: %7.3f s", timers[_t_computeLive].seconds());
tty->print_cr (" Regalloc Split: %7.3f s", timers[_t_regAllocSplit].seconds());
tty->print_cr (" Postalloc Copy Rem: %7.3f s", timers[_t_postAllocCopyRemoval].seconds());
+ tty->print_cr (" Merge multidefs: %7.3f s", timers[_t_mergeMultidefs].seconds());
tty->print_cr (" Fixup Spills: %7.3f s", timers[_t_fixupSpills].seconds());
tty->print_cr (" Compact: %7.3f s", timers[_t_chaitinCompact].seconds());
tty->print_cr (" Coalesce 1: %7.3f s", timers[_t_chaitinCoalesce1].seconds());
@@ -126,6 +127,7 @@
timers[_t_computeLive].seconds() +
timers[_t_regAllocSplit].seconds() +
timers[_t_postAllocCopyRemoval].seconds() +
+ timers[_t_mergeMultidefs].seconds() +
timers[_t_fixupSpills].seconds() +
timers[_t_chaitinCompact].seconds() +
timers[_t_chaitinCoalesce1].seconds() +
--- a/hotspot/src/share/vm/opto/phase.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/phase.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -88,6 +88,7 @@
_t_computeLive,
_t_regAllocSplit,
_t_postAllocCopyRemoval,
+ _t_mergeMultidefs,
_t_fixupSpills,
_t_chaitinCompact,
_t_chaitinCoalesce1,
--- a/hotspot/src/share/vm/opto/postaloc.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/postaloc.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -263,20 +263,6 @@
// intermediate copies might be illegal, i.e., value is stored down to stack
// then reloaded BUT survives in a register the whole way.
Node *val = skip_copies(n->in(k));
-
- if (val == x && nk_idx != 0 &&
- regnd[nk_reg] != NULL && regnd[nk_reg] != x &&
- _lrg_map.live_range_id(x) == _lrg_map.live_range_id(regnd[nk_reg])) {
- // When rematerialzing nodes and stretching lifetimes, the
- // allocator will reuse the original def for multidef LRG instead
- // of the current reaching def because it can't know it's safe to
- // do so. After allocation completes if they are in the same LRG
- // then it should use the current reaching def instead.
- n->set_req(k, regnd[nk_reg]);
- blk_adjust += yank_if_dead(val, current_block, &value, ®nd);
- val = skip_copies(n->in(k));
- }
-
if (val == x) return blk_adjust; // No progress?
int n_regs = RegMask::num_registers(val->ideal_reg());
@@ -382,6 +368,95 @@
return false;
}
+// The algorithms works as follows:
+// We traverse the block top to bottom. possibly_merge_multidef() is invoked for every input edge k
+// of the instruction n. We check to see if the input is a multidef lrg. If it is, we record the fact that we've
+// seen a definition (coming as an input) and add that fact to the reg2defuse array. The array maps registers to their
+// current reaching definitions (we track only multidefs though). With each definition we also associate the first
+// instruction we saw use it. If we encounter the situation when we observe an def (an input) that is a part of the
+// same lrg but is different from the previous seen def we merge the two with a MachMerge node and substitute
+// all the uses that we've seen so far to use the merge. After that we keep replacing the new defs in the same lrg
+// as they get encountered with the merge node and keep adding these defs to the merge inputs.
+void PhaseChaitin::merge_multidefs() {
+ Compile::TracePhase tp("mergeMultidefs", &timers[_t_mergeMultidefs]);
+ ResourceMark rm;
+ // Keep track of the defs seen in registers and collect their uses in the block.
+ RegToDefUseMap reg2defuse(_max_reg, _max_reg, RegDefUse());
+ for (uint i = 0; i < _cfg.number_of_blocks(); i++) {
+ Block* block = _cfg.get_block(i);
+ for (uint j = 1; j < block->number_of_nodes(); j++) {
+ Node* n = block->get_node(j);
+ if (n->is_Phi()) continue;
+ for (uint k = 1; k < n->req(); k++) {
+ j += possibly_merge_multidef(n, k, block, reg2defuse);
+ }
+ // Null out the value produced by the instruction itself, since we're only interested in defs
+ // implicitly defined by the uses. We are actually interested in tracking only redefinitions
+ // of the multidef lrgs in the same register. For that matter it's enough to track changes in
+ // the base register only and ignore other effects of multi-register lrgs and fat projections.
+ // It is also ok to ignore defs coming from singledefs. After an implicit overwrite by one of
+ // those our register is guaranteed to be used by another lrg and we won't attempt to merge it.
+ uint lrg = _lrg_map.live_range_id(n);
+ if (lrg > 0 && lrgs(lrg).is_multidef()) {
+ OptoReg::Name reg = lrgs(lrg).reg();
+ reg2defuse.at(reg).clear();
+ }
+ }
+ // Clear reg->def->use tracking for the next block
+ for (int j = 0; j < reg2defuse.length(); j++) {
+ reg2defuse.at(j).clear();
+ }
+ }
+}
+
+int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDefUseMap& reg2defuse) {
+ int blk_adjust = 0;
+
+ uint lrg = _lrg_map.live_range_id(n->in(k));
+ if (lrg > 0 && lrgs(lrg).is_multidef()) {
+ OptoReg::Name reg = lrgs(lrg).reg();
+
+ Node* def = reg2defuse.at(reg).def();
+ if (def != NULL && lrg == _lrg_map.live_range_id(def) && def != n->in(k)) {
+ // Same lrg but different node, we have to merge.
+ MachMergeNode* merge;
+ if (def->is_MachMerge()) { // is it already a merge?
+ merge = def->as_MachMerge();
+ } else {
+ merge = new MachMergeNode(def);
+
+ // Insert the merge node into the block before the first use.
+ uint use_index = block->find_node(reg2defuse.at(reg).first_use());
+ block->insert_node(merge, use_index++);
+ _cfg.map_node_to_block(merge, block);
+
+ // Let the allocator know about the new node, use the same lrg
+ _lrg_map.extend(merge->_idx, lrg);
+ blk_adjust++;
+
+ // Fixup all the uses (there is at least one) that happened between the first
+ // use and before the current one.
+ for (; use_index < block->number_of_nodes(); use_index++) {
+ Node* use = block->get_node(use_index);
+ if (use == n) {
+ break;
+ }
+ use->replace_edge(def, merge);
+ }
+ }
+ if (merge->find_edge(n->in(k)) == -1) {
+ merge->add_req(n->in(k));
+ }
+ n->set_req(k, merge);
+ }
+
+ // update the uses
+ reg2defuse.at(reg).update(n->in(k), n);
+ }
+
+ return blk_adjust;
+}
+
//------------------------------post_allocate_copy_removal---------------------
// Post-Allocation peephole copy removal. We do this in 1 pass over the
--- a/hotspot/src/share/vm/opto/stringopts.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/opto/stringopts.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1507,10 +1507,12 @@
}
case StringConcat::StringMode: {
const Type* type = kit.gvn().type(arg);
+ Node* count = NULL;
if (type == TypePtr::NULL_PTR) {
// replace the argument with the null checked version
arg = null_string;
sc->set_argument(argi, arg);
+ count = kit.load_String_length(kit.control(), arg);
} else if (!type->higher_equal(TypeInstPtr::NOTNULL)) {
// s = s != null ? s : "null";
// length = length + (s.count - s.offset);
@@ -1533,10 +1535,13 @@
// replace the argument with the null checked version
arg = phi;
sc->set_argument(argi, arg);
+ count = kit.load_String_length(kit.control(), arg);
+ } else {
+ // A corresponding nullcheck will be connected during IGVN MemNode::Ideal_common_DU_postCCP
+ // kit.control might be a different test, that can be hoisted above the actual nullcheck
+ // in case, that the control input is not null, Ideal_common_DU_postCCP will not look for a nullcheck.
+ count = kit.load_String_length(NULL, arg);
}
-
- Node* count = kit.load_String_length(kit.control(), arg);
-
length = __ AddI(length, count);
string_sizes->init_req(argi, NULL);
break;
--- a/hotspot/src/share/vm/prims/jvm.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvm.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -300,6 +300,48 @@
return os::javaTimeNanos();
JVM_END
+// The function below is actually exposed by sun.misc.VM and not
+// java.lang.System, but we choose to keep it here so that it stays next
+// to JVM_CurrentTimeMillis and JVM_NanoTime
+
+const jlong MAX_DIFF_SECS = 0x0100000000LL; // 2^32
+const jlong MIN_DIFF_SECS = -MAX_DIFF_SECS; // -2^32
+
+JVM_LEAF(jlong, JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs))
+ JVMWrapper("JVM_GetNanoTimeAdjustment");
+ jlong seconds;
+ jlong nanos;
+
+ os::javaTimeSystemUTC(seconds, nanos);
+
+ // We're going to verify that the result can fit in a long.
+ // For that we need the difference in seconds between 'seconds'
+ // and 'offset_secs' to be such that:
+ // |seconds - offset_secs| < (2^63/10^9)
+ // We're going to approximate 10^9 ~< 2^30 (1000^3 ~< 1024^3)
+ // which makes |seconds - offset_secs| < 2^33
+ // and we will prefer +/- 2^32 as the maximum acceptable diff
+ // as 2^32 has a more natural feel than 2^33...
+ //
+ // So if |seconds - offset_secs| >= 2^32 - we return a special
+ // sentinel value (-1) which the caller should take as an
+ // exception value indicating that the offset given to us is
+ // too far from range of the current time - leading to too big
+ // a nano adjustment. The caller is expected to recover by
+ // computing a more accurate offset and calling this method
+ // again. (For the record 2^32 secs is ~136 years, so that
+ // should rarely happen)
+ //
+ jlong diff = seconds - offset_secs;
+ if (diff >= MAX_DIFF_SECS || diff <= MIN_DIFF_SECS) {
+ return -1; // sentinel value: the offset is too far off the target
+ }
+
+ // return the adjustment. If you compute a time by adding
+ // this number of nanoseconds along with the number of seconds
+ // in the offset you should get the current UTC time.
+ return (diff * (jlong)1000000000) + nanos;
+JVM_END
JVM_ENTRY(void, JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
jobject dst, jint dst_pos, jint length))
@@ -1167,7 +1209,7 @@
Method* m_oop = object->klass()->uncached_lookup_method(
vmSymbols::run_method_name(),
vmSymbols::void_object_signature(),
- Klass::normal);
+ Klass::find_overpass);
methodHandle m (THREAD, m_oop);
if (m.is_null() || !m->is_method() || !m()->is_public() || m()->is_static()) {
THROW_MSG_0(vmSymbols::java_lang_InternalError(), "No run method");
--- a/hotspot/src/share/vm/prims/jvm.h Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvm.h Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -131,6 +131,9 @@
JNIEXPORT jlong JNICALL
JVM_NanoTime(JNIEnv *env, jclass ignored);
+JNIEXPORT jlong JNICALL
+JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs);
+
JNIEXPORT void JNICALL
JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
jobject dst, jint dst_pos, jint length);
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -68,11 +68,11 @@
~JvmtiConstantPoolReconstituter() {
if (_symmap != NULL) {
- os::free(_symmap);
+ delete _symmap;
_symmap = NULL;
}
if (_classmap != NULL) {
- os::free(_classmap);
+ delete _classmap;
_classmap = NULL;
}
}
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -3376,7 +3376,9 @@
// not yet in the vtable, because the vtable setup is in progress.
// This must be done after we adjust the default_methods and
// default_vtable_indices for methods already in the vtable.
+ // If redefining Unsafe, walk all the vtables looking for entries.
if (ik->vtable_length() > 0 && (_the_class_oop->is_interface()
+ || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
|| ik->is_subtype_of(_the_class_oop))) {
// ik->vtable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
@@ -3396,7 +3398,9 @@
// interface, then we have to call adjust_method_entries() for
// every InstanceKlass that has an itable since there isn't a
// subclass relationship between an interface and an InstanceKlass.
+ // If redefining Unsafe, walk all the itables looking for entries.
if (ik->itable_length() > 0 && (_the_class_oop->is_interface()
+ || _the_class_oop == SystemDictionary::misc_Unsafe_klass()
|| ik->is_subclass_of(_the_class_oop))) {
// ik->itable() creates a wrapper object; rm cleans it up
ResourceMark rm(_thread);
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1046,10 +1046,16 @@
{
assert(str->klass() == SystemDictionary::String_klass(), "not a string");
+ typeArrayOop s_value = java_lang_String::value(str);
+
+ // JDK-6584008: the value field may be null if a String instance is
+ // partially constructed.
+ if (s_value == NULL) {
+ return 0;
+ }
// get the string value and length
// (string value may be offset from the base)
int s_len = java_lang_String::length(str);
- typeArrayOop s_value = java_lang_String::value(str);
int s_offset = java_lang_String::offset(str);
jchar* value;
if (s_len > 0) {
--- a/hotspot/src/share/vm/prims/methodComparator.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/methodComparator.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -405,6 +405,8 @@
if (strcmp(_old_cp->string_at_noresolve(cpi_old),
_new_cp->string_at_noresolve(cpi_new)) != 0)
return false;
+ if (_old_cp->is_pseudo_string_at(cpi_old) || _new_cp->is_pseudo_string_at(cpi_new))
+ return (_old_cp->is_pseudo_string_at(cpi_old) == _new_cp->is_pseudo_string_at(cpi_new));
} else if (tag_old.is_klass() || tag_old.is_unresolved_klass()) {
// tag_old should be klass - 4881222
if (! (tag_new.is_unresolved_klass() || tag_new.is_klass()))
--- a/hotspot/src/share/vm/prims/nativeLookup.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/nativeLookup.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -393,7 +393,7 @@
// Find method and invoke standard lookup
methodHandle method (THREAD,
- klass->uncached_lookup_method(m_name, s_name, Klass::normal));
+ klass->uncached_lookup_method(m_name, s_name, Klass::find_overpass));
address result = lookup(method, in_base_library, CATCH);
assert(in_base_library, "must be in basic library");
guarantee(result != NULL, "must be non NULL");
--- a/hotspot/src/share/vm/prims/perf.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/perf.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -100,6 +100,11 @@
PerfWrapper("Perf_Detach");
+ if (!UsePerfData) {
+ // With -XX:-UsePerfData, detach is just a NOP
+ return;
+ }
+
void* address = 0;
jlong capacity = 0;
--- a/hotspot/src/share/vm/prims/unsafe.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1104,43 +1104,6 @@
-UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_MonitorEnter");
- {
- if (jobj == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
- Handle obj(thread, JNIHandles::resolve_non_null(jobj));
- ObjectSynchronizer::jni_enter(obj, CHECK);
- }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_TryMonitorEnter");
- {
- if (jobj == NULL) {
- THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
- }
- Handle obj(thread, JNIHandles::resolve_non_null(jobj));
- bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
- return (res ? JNI_TRUE : JNI_FALSE);
- }
-UNSAFE_END
-
-
-UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
- UnsafeWrapper("Unsafe_MonitorExit");
- {
- if (jobj == NULL) {
- THROW(vmSymbols::java_lang_NullPointerException());
- }
- Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
- ObjectSynchronizer::jni_exit(obj(), CHECK);
- }
-UNSAFE_END
-
-
UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
UnsafeWrapper("Unsafe_ThrowException");
{
@@ -1365,8 +1328,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
};
@@ -1411,8 +1372,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
};
@@ -1461,8 +1420,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1515,9 +1472,6 @@
{CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
@@ -1571,9 +1525,6 @@
{CC"defineClass", CC"("DC_Args")"CLS, FN_PTR(Unsafe_DefineClass)},
{CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
- {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
- {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
- {CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
{CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
{CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
{CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -155,7 +155,7 @@
if (mdo != NULL) {
int i = mdo->invocation_count_delta();
int b = mdo->backedge_count_delta();
- return call_predicate_helper<CompLevel_full_profile>(i, b, 1);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, 1, method);
}
return false;
}
@@ -229,32 +229,32 @@
// Tier?LoadFeedback is basically a coefficient that determines of
// how many methods per compiler thread can be in the queue before
// the threshold values double.
-bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
- return loop_predicate_helper<CompLevel_none>(i, b, k);
+ return loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
- return loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
}
}
-bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool AdvancedThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
double k = threshold_scale(CompLevel_full_profile, Tier3LoadFeedback);
- return call_predicate_helper<CompLevel_none>(i, b, k);
+ return call_predicate_helper<CompLevel_none>(i, b, k, method);
}
case CompLevel_full_profile: {
double k = threshold_scale(CompLevel_full_optimization, Tier4LoadFeedback);
- return call_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
default:
return true;
@@ -271,7 +271,7 @@
int i = method->invocation_count();
int b = method->backedge_count();
double k = Tier0ProfilingStartPercentage / 100.0;
- return call_predicate_helper<CompLevel_none>(i, b, k) || loop_predicate_helper<CompLevel_none>(i, b, k);
+ return call_predicate_helper<CompLevel_none>(i, b, k, method) || loop_predicate_helper<CompLevel_none>(i, b, k, method);
}
return false;
}
@@ -348,7 +348,7 @@
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile, disable_feedback) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
- } else if ((this->*p)(i, b, cur_level)) {
+ } else if ((this->*p)(i, b, cur_level, method)) {
// C1-generated fully profiled code is about 30% slower than the limited profile
// code that has only invocation and backedge counters. The observation is that
// if C2 queue is large enough we can spend too much time in the fully profiled code
@@ -374,7 +374,7 @@
if (mdo->would_profile()) {
if (disable_feedback || (CompileBroker::queue_size(CompLevel_full_optimization) <=
Tier3DelayOff * compiler_count(CompLevel_full_optimization) &&
- (this->*p)(i, b, cur_level))) {
+ (this->*p)(i, b, cur_level, method))) {
next_level = CompLevel_full_profile;
}
} else {
@@ -390,7 +390,7 @@
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
- if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+ if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -84,7 +84,7 @@
* invocation and backedge notifications. Basically every n-th invocation or backedge a mutator thread
* makes a call into the runtime.
*
- * - Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
+ * - Tier?InvocationThreshold, Tier?CompileThreshold, Tier?BackEdgeThreshold, Tier?MinInvocationThreshold control
* compilation thresholds.
* Level 2 thresholds are not used and are provided for option-compatibility and potential future use.
* Other thresholds work as follows:
@@ -100,7 +100,9 @@
* The same predicate is used to control the transition from level 3 to level 4 (C2). It should be
* noted though that the thresholds are relative. Moreover i and b for the 0->3 transition come
* from Method* and for 3->4 transition they come from MDO (since profiled invocations are
- * counted separately).
+ * counted separately). Finally, if a method does not contain anything worth profiling, a transition
+ * from level 3 to level 4 occurs without considering thresholds (e.g., with fewer invocations than
+ * what is specified by Tier4InvocationThreshold).
*
* OSR transitions are controlled simply with b > TierXBackEdgeThreshold * s predicates.
*
@@ -164,9 +166,9 @@
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common().
// Predicates also take compiler load into account.
- typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
- bool call_predicate(int i, int b, CompLevel cur_level);
- bool loop_predicate(int i, int b, CompLevel cur_level);
+ typedef bool (AdvancedThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+ bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+ bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level, bool disable_feedback = false);
// Transition functions.
--- a/hotspot/src/share/vm/runtime/arguments.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1126,16 +1126,35 @@
}
#endif
-// Returns threshold scaled with CompileThresholdScaling
-intx Arguments::get_scaled_compile_threshold(intx threshold) {
- return (intx)(threshold * CompileThresholdScaling);
+intx Arguments::scaled_compile_threshold(intx threshold, double scale) {
+ if (scale == 1.0 || scale <= 0.0) {
+ return threshold;
+ } else {
+ return (intx)(threshold * scale);
+ }
}
// Returns freq_log scaled with CompileThresholdScaling
-intx Arguments::get_scaled_freq_log(intx freq_log) {
- intx scaled_freq = get_scaled_compile_threshold((intx)1 << freq_log);
- if (scaled_freq == 0) {
- return 0;
+intx Arguments::scaled_freq_log(intx freq_log, double scale) {
+ // Check if scaling is necessary or negative value was specified.
+ if (scale == 1.0 || scale < 0.0) {
+ return freq_log;
+ }
+
+ // Check value to avoid calculating log2 of 0.
+ if (scale == 0.0) {
+ return freq_log;
+ }
+
+ intx scaled_freq = scaled_compile_threshold((intx)1 << freq_log, scale);
+ // Determine the maximum notification frequency value currently supported.
+ // The largest mask value that the interpreter/C1 can handle is
+ // of length InvocationCounter::number_of_count_bits. Mask values are always
+ // one bit shorter then the value of the notification frequency. Set
+ // max_freq_bits accordingly.
+ intx max_freq_bits = InvocationCounter::number_of_count_bits + 1;
+ if (scaled_freq > nth_bit(max_freq_bits)) {
+ return max_freq_bits;
} else {
return log2_intptr(scaled_freq);
}
@@ -1180,31 +1199,36 @@
Tier3InvokeNotifyFreqLog = 0;
Tier4InvocationThreshold = 0;
}
+
+ if (CompileThresholdScaling < 0) {
+ vm_exit_during_initialization("Negative value specified for CompileThresholdScaling", NULL);
+ }
+
// Scale tiered compilation thresholds
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
- FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, get_scaled_freq_log(Tier0InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, get_scaled_freq_log(Tier0BackedgeNotifyFreqLog));
-
- FLAG_SET_ERGO(intx, Tier3InvocationThreshold, get_scaled_compile_threshold(Tier3InvocationThreshold));
- FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, get_scaled_compile_threshold(Tier3MinInvocationThreshold));
- FLAG_SET_ERGO(intx, Tier3CompileThreshold, get_scaled_compile_threshold(Tier3CompileThreshold));
- FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, get_scaled_compile_threshold(Tier3BackEdgeThreshold));
+ FLAG_SET_ERGO(intx, Tier0InvokeNotifyFreqLog, scaled_freq_log(Tier0InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier0BackedgeNotifyFreqLog, scaled_freq_log(Tier0BackedgeNotifyFreqLog));
+
+ FLAG_SET_ERGO(intx, Tier3InvocationThreshold, scaled_compile_threshold(Tier3InvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier3MinInvocationThreshold, scaled_compile_threshold(Tier3MinInvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier3CompileThreshold, scaled_compile_threshold(Tier3CompileThreshold));
+ FLAG_SET_ERGO(intx, Tier3BackEdgeThreshold, scaled_compile_threshold(Tier3BackEdgeThreshold));
// Tier2{Invocation,MinInvocation,Compile,Backedge}Threshold should be scaled here
// once these thresholds become supported.
- FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, get_scaled_freq_log(Tier2InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, get_scaled_freq_log(Tier2BackedgeNotifyFreqLog));
-
- FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, get_scaled_freq_log(Tier3InvokeNotifyFreqLog));
- FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, get_scaled_freq_log(Tier3BackedgeNotifyFreqLog));
-
- FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, get_scaled_freq_log(Tier23InlineeNotifyFreqLog));
-
- FLAG_SET_ERGO(intx, Tier4InvocationThreshold, get_scaled_compile_threshold(Tier4InvocationThreshold));
- FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, get_scaled_compile_threshold(Tier4MinInvocationThreshold));
- FLAG_SET_ERGO(intx, Tier4CompileThreshold, get_scaled_compile_threshold(Tier4CompileThreshold));
- FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, get_scaled_compile_threshold(Tier4BackEdgeThreshold));
+ FLAG_SET_ERGO(intx, Tier2InvokeNotifyFreqLog, scaled_freq_log(Tier2InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier2BackedgeNotifyFreqLog, scaled_freq_log(Tier2BackedgeNotifyFreqLog));
+
+ FLAG_SET_ERGO(intx, Tier3InvokeNotifyFreqLog, scaled_freq_log(Tier3InvokeNotifyFreqLog));
+ FLAG_SET_ERGO(intx, Tier3BackedgeNotifyFreqLog, scaled_freq_log(Tier3BackedgeNotifyFreqLog));
+
+ FLAG_SET_ERGO(intx, Tier23InlineeNotifyFreqLog, scaled_freq_log(Tier23InlineeNotifyFreqLog));
+
+ FLAG_SET_ERGO(intx, Tier4InvocationThreshold, scaled_compile_threshold(Tier4InvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier4MinInvocationThreshold, scaled_compile_threshold(Tier4MinInvocationThreshold));
+ FLAG_SET_ERGO(intx, Tier4CompileThreshold, scaled_compile_threshold(Tier4CompileThreshold));
+ FLAG_SET_ERGO(intx, Tier4BackEdgeThreshold, scaled_compile_threshold(Tier4BackEdgeThreshold));
}
}
@@ -3455,8 +3479,10 @@
set_mode_flags(_int);
}
- if ((TieredCompilation && CompileThresholdScaling == 0)
- || (!TieredCompilation && get_scaled_compile_threshold(CompileThreshold) == 0)) {
+ // CompileThresholdScaling == 0.0 is same as -Xint: Disable compilation (enable interpreter-only mode),
+ // but like -Xint, leave compilation thresholds unaffected.
+ // With tiered compilation disabled, setting CompileThreshold to 0 disables compilation as well.
+ if ((CompileThresholdScaling == 0.0) || (!TieredCompilation && CompileThreshold == 0)) {
set_mode_flags(_int);
}
@@ -3896,7 +3922,7 @@
}
// Scale CompileThreshold
if (!FLAG_IS_DEFAULT(CompileThresholdScaling)) {
- FLAG_SET_ERGO(intx, CompileThreshold, get_scaled_compile_threshold(CompileThreshold));
+ FLAG_SET_ERGO(intx, CompileThreshold, scaled_compile_threshold(CompileThreshold));
}
}
--- a/hotspot/src/share/vm/runtime/arguments.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -328,9 +328,6 @@
static bool _ClipInlining;
static bool _CIDynamicCompilePriority;
- // Scale compile thresholds
- static intx get_scaled_compile_threshold(intx threshold);
- static intx get_scaled_freq_log(intx freq_log);
// Tiered
static void set_tiered_flags();
static int get_min_number_of_compiler_threads();
@@ -452,6 +449,18 @@
static char* SharedArchivePath;
public:
+ // Scale compile thresholds
+ // Returns threshold scaled with CompileThresholdScaling
+ static intx scaled_compile_threshold(intx threshold, double scale);
+ static intx scaled_compile_threshold(intx threshold) {
+ return scaled_compile_threshold(threshold, CompileThresholdScaling);
+ }
+ // Returns freq_log scaled with CompileThresholdScaling
+ static intx scaled_freq_log(intx freq_log, double scale);
+ static intx scaled_freq_log(intx freq_log) {
+ return scaled_freq_log(freq_log, CompileThresholdScaling);
+ }
+
// Parses the arguments, first phase
static jint parse(const JavaVMInitArgs* args);
// Apply ergonomics
--- a/hotspot/src/share/vm/runtime/globals.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/globals.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -2477,7 +2477,7 @@
"Number of compiler threads to run") \
\
product(intx, CompilationPolicyChoice, 0, \
- "which compilation policy (0/1)") \
+ "which compilation policy (0-3)") \
\
develop(bool, UseStackBanging, true, \
"use stack banging for stack overflow checks (required for " \
@@ -3528,7 +3528,16 @@
\
product(double, CompileThresholdScaling, 1.0, \
"Factor to control when first compilation happens " \
- "(both with and without tiered compilation)") \
+ "(both with and without tiered compilation): " \
+ "values greater than 1.0 delay counter overflow, " \
+ "values between 0 and 1.0 rush counter overflow, " \
+ "value of 1.0 leave compilation thresholds unchanged " \
+ "value of 0.0 is equivalent to -Xint. " \
+ "" \
+ "Flag can be set as per-method option. " \
+ "If a value is specified for a method, compilation thresholds " \
+ "for that method are scaled by both the value of the global flag "\
+ "and the value of the per-method flag.") \
\
product(intx, Tier0InvokeNotifyFreqLog, 7, \
"Interpreter (tier 0) invocation notification frequency") \
--- a/hotspot/src/share/vm/runtime/os.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/os.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1401,15 +1401,17 @@
return (sp > (stack_limit + reserved_area));
}
-size_t os::page_size_for_region(size_t region_size, size_t min_pages) {
+size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned) {
assert(min_pages > 0, "sanity");
if (UseLargePages) {
const size_t max_page_size = region_size / min_pages;
for (size_t i = 0; _page_sizes[i] != 0; ++i) {
const size_t page_size = _page_sizes[i];
- if (page_size <= max_page_size && is_size_aligned(region_size, page_size)) {
- return page_size;
+ if (page_size <= max_page_size) {
+ if (!must_be_aligned || is_size_aligned(region_size, page_size)) {
+ return page_size;
+ }
}
}
}
@@ -1417,6 +1419,14 @@
return vm_page_size();
}
+size_t os::page_size_for_region_aligned(size_t region_size, size_t min_pages) {
+ return page_size_for_region(region_size, min_pages, true);
+}
+
+size_t os::page_size_for_region_unaligned(size_t region_size, size_t min_pages) {
+ return page_size_for_region(region_size, min_pages, false);
+}
+
#ifndef PRODUCT
void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count)
{
@@ -1665,17 +1675,17 @@
static size_t large_page_size() {
const size_t large_page_size_example = 4 * M;
- return os::page_size_for_region(large_page_size_example, 1);
+ return os::page_size_for_region_aligned(large_page_size_example, 1);
}
- static void test_page_size_for_region() {
+ static void test_page_size_for_region_aligned() {
if (UseLargePages) {
const size_t small_page = small_page_size();
const size_t large_page = large_page_size();
if (large_page > small_page) {
size_t num_small_pages_in_large = large_page / small_page;
- size_t page = os::page_size_for_region(large_page, num_small_pages_in_large);
+ size_t page = os::page_size_for_region_aligned(large_page, num_small_pages_in_large);
assert_eq(page, small_page);
}
@@ -1688,21 +1698,53 @@
const size_t large_page = large_page_size();
if (large_page > small_page) {
const size_t unaligned_region = large_page + 17;
- size_t page = os::page_size_for_region(unaligned_region, 1);
+ size_t page = os::page_size_for_region_aligned(unaligned_region, 1);
assert_eq(page, small_page);
const size_t num_pages = 5;
const size_t aligned_region = large_page * num_pages;
- page = os::page_size_for_region(aligned_region, num_pages);
+ page = os::page_size_for_region_aligned(aligned_region, num_pages);
assert_eq(page, large_page);
}
}
}
+ static void test_page_size_for_region_unaligned() {
+ if (UseLargePages) {
+ // Given exact page size, should return that page size.
+ for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+ size_t expected = os::_page_sizes[i];
+ size_t actual = os::page_size_for_region_unaligned(expected, 1);
+ assert_eq(expected, actual);
+ }
+
+ // Given slightly larger size than a page size, return the page size.
+ for (size_t i = 0; os::_page_sizes[i] != 0; i++) {
+ size_t expected = os::_page_sizes[i];
+ size_t actual = os::page_size_for_region_unaligned(expected + 17, 1);
+ assert_eq(expected, actual);
+ }
+
+ // Given a slightly smaller size than a page size,
+ // return the next smaller page size.
+ if (os::_page_sizes[1] > os::_page_sizes[0]) {
+ size_t expected = os::_page_sizes[0];
+ size_t actual = os::page_size_for_region_unaligned(os::_page_sizes[1] - 17, 1);
+ assert_eq(actual, expected);
+ }
+
+ // Return small page size for values less than a small page.
+ size_t small_page = small_page_size();
+ size_t actual = os::page_size_for_region_unaligned(small_page - 17, 1);
+ assert_eq(small_page, actual);
+ }
+ }
+
public:
static void run_tests() {
- test_page_size_for_region();
+ test_page_size_for_region_aligned();
test_page_size_for_region_alignment();
+ test_page_size_for_region_unaligned();
}
};
--- a/hotspot/src/share/vm/runtime/os.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/os.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -148,6 +148,7 @@
static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint);
static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint);
+ static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned);
public:
static void init(void); // Called before command line parsing
@@ -172,10 +173,10 @@
static jlong javaTimeMillis();
static jlong javaTimeNanos();
static void javaTimeNanos_info(jvmtiTimerInfo *info_ptr);
+ static void javaTimeSystemUTC(jlong &seconds, jlong &nanos);
static void run_periodic_checks();
static bool supports_monotonic_clock();
-
// Returns the elapsed time in seconds since the vm started.
static double elapsedTime();
@@ -267,8 +268,13 @@
// Returns the page size to use for a region of memory.
// region_size / min_pages will always be greater than or equal to the
- // returned value.
- static size_t page_size_for_region(size_t region_size, size_t min_pages);
+ // returned value. The returned value will divide region_size.
+ static size_t page_size_for_region_aligned(size_t region_size, size_t min_pages);
+
+ // Returns the page size to use for a region of memory.
+ // region_size / min_pages will always be greater than or equal to the
+ // returned value. The returned value might not divide region_size.
+ static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages);
// Return the largest page size that can be used
static size_t max_page_size() {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -257,28 +257,28 @@
// Call and loop predicates determine whether a transition to a higher
// compilation level should be performed (pointers to predicate functions
// are passed to common() transition function).
-bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::loop_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
- return loop_predicate_helper<CompLevel_none>(i, b, 1.0);
+ return loop_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
- return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+ return loop_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
}
}
-bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level) {
+bool SimpleThresholdPolicy::call_predicate(int i, int b, CompLevel cur_level, Method* method) {
switch(cur_level) {
case CompLevel_none:
case CompLevel_limited_profile: {
- return call_predicate_helper<CompLevel_none>(i, b, 1.0);
+ return call_predicate_helper<CompLevel_none>(i, b, 1.0, method);
}
case CompLevel_full_profile: {
- return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, 1.0, method);
}
default:
return true;
@@ -293,8 +293,8 @@
int i = mdo->invocation_count();
int b = mdo->backedge_count();
double k = ProfileMaturityPercentage / 100.0;
- return call_predicate_helper<CompLevel_full_profile>(i, b, k) ||
- loop_predicate_helper<CompLevel_full_profile>(i, b, k);
+ return call_predicate_helper<CompLevel_full_profile>(i, b, k, method) ||
+ loop_predicate_helper<CompLevel_full_profile>(i, b, k, method);
}
return false;
}
@@ -313,7 +313,7 @@
// If we were at full profile level, would we switch to full opt?
if (common(p, method, CompLevel_full_profile) == CompLevel_full_optimization) {
next_level = CompLevel_full_optimization;
- } else if ((this->*p)(i, b, cur_level)) {
+ } else if ((this->*p)(i, b, cur_level, method)) {
next_level = CompLevel_full_profile;
}
break;
@@ -325,7 +325,7 @@
if (mdo->would_profile()) {
int mdo_i = mdo->invocation_count_delta();
int mdo_b = mdo->backedge_count_delta();
- if ((this->*p)(mdo_i, mdo_b, cur_level)) {
+ if ((this->*p)(mdo_i, mdo_b, cur_level, method)) {
next_level = CompLevel_full_optimization;
}
} else {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -43,9 +43,9 @@
// Call and loop predicates determine whether a transition to a higher compilation
// level should be performed (pointers to predicate functions are passed to common_TF().
// Predicates also take compiler load into account.
- typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level);
- bool call_predicate(int i, int b, CompLevel cur_level);
- bool loop_predicate(int i, int b, CompLevel cur_level);
+ typedef bool (SimpleThresholdPolicy::*Predicate)(int i, int b, CompLevel cur_level, Method* method);
+ bool call_predicate(int i, int b, CompLevel cur_level, Method* method);
+ bool loop_predicate(int i, int b, CompLevel cur_level, Method* method);
// Common transition function. Given a predicate determines if a method should transition to another level.
CompLevel common(Predicate p, Method* method, CompLevel cur_level);
// Transition functions.
@@ -76,8 +76,8 @@
// Predicate helpers are used by .*_predicate() methods as well as others.
// They check the given counter values, multiplied by the scale against the thresholds.
- template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale);
- template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale);
+ template<CompLevel level> static inline bool call_predicate_helper(int i, int b, double scale, Method* method);
+ template<CompLevel level> static inline bool loop_predicate_helper(int i, int b, double scale, Method* method);
// Get a compilation level for a given method.
static CompLevel comp_level(Method* method) {
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -25,8 +25,14 @@
#ifndef SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
#define SHARE_VM_RUNTIME_SIMPLETHRESHOLDPOLICY_INLINE_HPP
+#include "compiler/compilerOracle.hpp"
+
template<CompLevel level>
-bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::call_predicate_helper(int i, int b, double scale, Method* method) {
+ double threshold_scaling;
+ if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+ scale *= threshold_scaling;
+ }
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:
@@ -40,7 +46,11 @@
}
template<CompLevel level>
-bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) {
+bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale, Method* method) {
+ double threshold_scaling;
+ if (CompilerOracle::has_option_value(method, "CompileThresholdScaling", threshold_scaling)) {
+ scale *= threshold_scaling;
+ }
switch(level) {
case CompLevel_none:
case CompLevel_limited_profile:
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -276,18 +276,6 @@
THREAD->set_current_pending_monitor_is_from_java(true);
}
-// NOTE: must use heavy weight monitor to handle jni monitor enter
-bool ObjectSynchronizer::jni_try_enter(Handle obj, Thread* THREAD) {
- if (UseBiasedLocking) {
- BiasedLocking::revoke_and_rebias(obj, false, THREAD);
- assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
- }
-
- ObjectMonitor* monitor = ObjectSynchronizer::inflate_helper(obj());
- return monitor->try_enter(THREAD);
-}
-
-
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
TEVENT(jni_exit);
--- a/hotspot/src/share/vm/runtime/synchronizer.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/synchronizer.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,7 +65,6 @@
// Used only to handle jni locks or other unmatched monitor enter/exit
// Internally they will use heavy weight monitor.
static void jni_enter(Handle obj, TRAPS);
- static bool jni_try_enter(Handle obj, Thread* THREAD); // Implements Unsafe.tryMonitorEnter
static void jni_exit(oop obj, Thread* THREAD);
// Handle all interpreter, compiler and jni cases
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -38,7 +38,8 @@
}
ReservedSpace::ReservedSpace(size_t size) {
- size_t page_size = os::page_size_for_region(size, 1);
+ // Want to use large pages where possible and pad with small pages.
+ size_t page_size = os::page_size_for_region_unaligned(size, 1);
bool large_pages = page_size != (size_t)os::vm_page_size();
// Don't force the alignment to be large page aligned,
// since that will waste memory.
@@ -617,7 +618,7 @@
bool VirtualSpace::initialize(ReservedSpace rs, size_t committed_size) {
- const size_t max_commit_granularity = os::page_size_for_region(rs.size(), 1);
+ const size_t max_commit_granularity = os::page_size_for_region_unaligned(rs.size(), 1);
return initialize_with_granularity(rs, committed_size, max_commit_granularity);
}
@@ -1239,7 +1240,7 @@
case Disable:
return vs.initialize_with_granularity(rs, 0, os::vm_page_size());
case Commit:
- return vs.initialize_with_granularity(rs, 0, os::page_size_for_region(rs.size(), 1));
+ return vs.initialize_with_granularity(rs, 0, os::page_size_for_region_unaligned(rs.size(), 1));
}
}
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Feb 09 09:52:48 2015 -0800
@@ -351,11 +351,18 @@
nonstatic_field(MethodData, _arg_stack, intx) \
nonstatic_field(MethodData, _arg_returned, intx) \
nonstatic_field(MethodData, _tenure_traps, uint) \
+ nonstatic_field(MethodData, _invoke_mask, int) \
+ nonstatic_field(MethodData, _backedge_mask, int) \
nonstatic_field(DataLayout, _header._struct._tag, u1) \
nonstatic_field(DataLayout, _header._struct._flags, u1) \
nonstatic_field(DataLayout, _header._struct._bci, u2) \
nonstatic_field(DataLayout, _cells[0], intptr_t) \
nonstatic_field(MethodCounters, _nmethod_age, int) \
+ nonstatic_field(MethodCounters, _interpreter_invocation_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_backward_branch_limit, int) \
+ nonstatic_field(MethodCounters, _interpreter_profile_limit, int) \
+ nonstatic_field(MethodCounters, _invoke_mask, int) \
+ nonstatic_field(MethodCounters, _backedge_mask, int) \
nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \
nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \
nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp Mon Feb 09 09:52:48 2015 -0800
@@ -1142,17 +1142,18 @@
return ((x != NoLongBits) && (mask_long_bits(x, x - 1) == NoLongBits));
}
-//* largest i such that 2^i <= x
-// A negative value of 'x' will return '31'
+// Returns largest i such that 2^i <= x.
+// If x < 0, the function returns 31 on a 32-bit machine and 63 on a 64-bit machine.
+// If x == 0, the function returns -1.
inline int log2_intptr(intptr_t x) {
int i = -1;
- uintptr_t p = 1;
+ uintptr_t p = 1;
while (p != 0 && p <= (uintptr_t)x) {
// p = 2^(i+1) && p <= x (i.e., 2^(i+1) <= x)
i++; p *= 2;
}
// p = 2^(i+1) && x < p (i.e., 2^i <= x < 2^(i+1))
- // (if p = 0 then overflow occurred and i = 31)
+ // If p = 0, overflow has occurred and i = 31 or i = 63 (depending on the machine word size).
return i;
}
--- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java Mon Feb 09 09:52:48 2015 -0800
@@ -54,7 +54,7 @@
//
// Tier0InvokeNotifyFreqLog, Tier0BackedgeNotifyFreqLog,
// Tier3InvocationThreshold, Tier3MinInvocationThreshold,
- // Tier3CompileThreshold, and Tier3BackEdgeThreshold,
+ // Tier3CompileThreshold, Tier3BackEdgeThreshold,
// Tier2InvokeNotifyFreqLog, Tier2BackedgeNotifyFreqLog,
// Tier3InvokeNotifyFreqLog, Tier3BackedgeNotifyFreqLog,
// Tier23InlineeNotifyFreqLog, Tier4InvocationThreshold,
@@ -87,6 +87,13 @@
{
"-XX:-TieredCompilation",
"-XX:+PrintFlagsFinal",
+ "-XX:CompileThreshold=1000",
+ "-XX:CompileThresholdScaling=0.0",
+ "-version"
+ },
+ {
+ "-XX:-TieredCompilation",
+ "-XX:+PrintFlagsFinal",
"-XX:CompileThreshold=0",
"-XX:CompileThresholdScaling=0.75",
"-version"
@@ -108,6 +115,11 @@
"double CompileThresholdScaling := 0.750000 {product}"
},
{
+ "intx CompileThreshold := 1000 {pd product}",
+ "double CompileThresholdScaling := 0.000000 {product}",
+ "interpreted mode"
+ },
+ {
"intx CompileThreshold := 0 {pd product}",
"double CompileThresholdScaling := 0.750000 {product}",
"interpreted mode"
@@ -295,21 +307,21 @@
"double CompileThresholdScaling := 2.000000 {product}"
},
{
- "intx Tier0BackedgeNotifyFreqLog := 0 {product}",
- "intx Tier0InvokeNotifyFreqLog := 0 {product}",
- "intx Tier23InlineeNotifyFreqLog := 0 {product}",
- "intx Tier2BackedgeNotifyFreqLog := 0 {product}",
- "intx Tier2InvokeNotifyFreqLog := 0 {product}",
- "intx Tier3BackEdgeThreshold := 0 {product}",
- "intx Tier3BackedgeNotifyFreqLog := 0 {product}",
- "intx Tier3CompileThreshold := 0 {product}",
- "intx Tier3InvocationThreshold := 0 {product}",
- "intx Tier3InvokeNotifyFreqLog := 0 {product}",
- "intx Tier3MinInvocationThreshold := 0 {product}",
- "intx Tier4BackEdgeThreshold := 0 {product}",
- "intx Tier4CompileThreshold := 0 {product}",
- "intx Tier4InvocationThreshold := 0 {product}",
- "intx Tier4MinInvocationThreshold := 0 {product}",
+ "intx Tier0BackedgeNotifyFreqLog := 10 {product}",
+ "intx Tier0InvokeNotifyFreqLog := 7 {product}",
+ "intx Tier23InlineeNotifyFreqLog := 20 {product}",
+ "intx Tier2BackedgeNotifyFreqLog := 14 {product}",
+ "intx Tier2InvokeNotifyFreqLog := 11 {product}",
+ "intx Tier3BackEdgeThreshold := 60000 {product}",
+ "intx Tier3BackedgeNotifyFreqLog := 13 {product}",
+ "intx Tier3CompileThreshold := 2000 {product}",
+ "intx Tier3InvocationThreshold := 200 {product}",
+ "intx Tier3InvokeNotifyFreqLog := 10 {product}",
+ "intx Tier3MinInvocationThreshold := 100 {product}",
+ "intx Tier4BackEdgeThreshold := 40000 {product}",
+ "intx Tier4CompileThreshold := 15000 {product}",
+ "intx Tier4InvocationThreshold := 5000 {product}",
+ "intx Tier4MinInvocationThreshold := 600 {product}",
"double CompileThresholdScaling := 0.000000 {product}",
"interpreted mode"
}
--- a/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java Mon Feb 09 09:52:48 2015 -0800
@@ -82,6 +82,9 @@
ExitCode.OK,
testCaseDescription.getTestOptions(options,
CommandLineOptionTest.prepareBooleanFlag(
- "PrintCodeCache", printCodeCache)));
+ "PrintCodeCache", printCodeCache),
+ // Do not use large pages to avoid large page
+ // alignment of code heaps affecting their size.
+ "-XX:-UseLargePages"));
}
}
--- a/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/codecache/jmx/PoolsIndependenceTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -98,11 +98,13 @@
return false;
});
for (BlobType bt : BlobType.getAvailable()) {
- int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
- Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
- expectedNotificationsAmount, String.format("Unexpected "
- + "amount of notifications for pool: %s",
- bt.getMemoryPool().getName()));
+ if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+ int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
+ Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(),
+ expectedNotificationsAmount, String.format("Unexpected "
+ + "amount of notifications for pool: %s",
+ bt.getMemoryPool().getName()));
+ }
}
try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()).
--- a/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/codecache/jmx/ThresholdNotificationsTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -52,7 +52,9 @@
public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) {
- new ThresholdNotificationsTest(bt).runTest();
+ if (CodeCacheUtils.isCodeHeapPredictable(bt)) {
+ new ThresholdNotificationsTest(bt).runTest();
+ }
}
}
--- a/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Mon Feb 09 09:52:48 2015 -0800
@@ -36,7 +36,7 @@
try {
// adjust timeout and substract vm init and exit time
long timeout = Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT);
- timeout *= 0.9;
+ timeout *= 0.8;
new TimeLimitedRunner(timeout, 2.0d, this::test).call();
} catch (Exception e) {
throw new Error("Exception occurred during test execution", e);
--- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -77,7 +77,7 @@
}
public OverloadCompileQueueTest() {
- Helper.startInfiniteLoopThread(this::lockUnlock);
+ Helper.startInfiniteLoopThread(this::lockUnlock, 100L);
}
@Override
@@ -99,8 +99,9 @@
private void lockUnlock() {
try {
+ int sleep = Helper.RNG.nextInt(MAX_SLEEP);
Helper.WHITE_BOX.lockCompilation();
- Thread.sleep(Helper.RNG.nextInt(MAX_SLEEP));
+ Thread.sleep(sleep);
} catch (InterruptedException e) {
throw new Error("TESTBUG: lockUnlocker thread was unexpectedly interrupted", e);
} finally {
--- a/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java Mon Feb 09 09:52:48 2015 -0800
@@ -26,7 +26,6 @@
* @bug 8042235
* @summary redefining method used by multiple MethodHandles crashes VM
* @compile -XDignore.symbol.file RedefineMethodUsedByMultipleMethodHandles.java
- * @ignore 7076820
* @run main RedefineMethodUsedByMultipleMethodHandles
*/
--- a/hotspot/test/compiler/loopopts/7052494/Test7052494.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/loopopts/7052494/Test7052494.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,7 +25,6 @@
/**
* @test
* @bug 7052494
- * @ignore 7154567
* @summary Eclipse test fails on JDK 7 b142
*
* @run main/othervm -Xbatch Test7052494
--- a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Mon Feb 09 09:52:48 2015 -0800
@@ -21,12 +21,15 @@
* questions.
*/
+import java.io.PrintWriter;
+import java.io.File;
+
import com.oracle.java.testlibrary.*;
/*
* @test CheckCompileCommandOption
- * @bug 8055286 8056964 8059847
- * @summary "Checks parsing of -XX:+CompileCommand=option"
+ * @bug 8055286 8056964 8059847 8069035
+ * @summary "Checks parsing of -XX:CompileCommand=option"
* @library /testlibrary
* @run main CheckCompileCommandOption
*/
@@ -45,38 +48,69 @@
// have the the following types: intx, uintx, bool, ccstr,
// ccstrlist, and double.
+ private static final String[][] FILE_ARGUMENTS = {
+ {
+ "-XX:CompileCommandFile=" + new File(System.getProperty("test.src", "."), "command1.txt"),
+ "-version"
+ },
+ {
+ "-XX:CompileCommandFile=" + new File(System.getProperty("test.src", "."), "command2.txt"),
+ "-version"
+ }
+ };
+
+ private static final String[][] FILE_EXPECTED_OUTPUT = {
+ {
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption4 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption9 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption10 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption11 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption12 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption13 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption14 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption15 = true",
+ "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption16 = true"
+ },
+ {
+ "CompileCommand: option Test.test const char* MyListOption = '_foo _bar'",
+ "CompileCommand: option Test.test const char* MyStrOption = '_foo'",
+ "CompileCommand: option Test.test bool MyBoolOption = false",
+ "CompileCommand: option Test.test intx MyIntxOption = -1",
+ "CompileCommand: option Test.test uintx MyUintxOption = 1",
+ "CompileCommand: option Test.test bool MyFlag = true",
+ "CompileCommand: option Test.test double MyDoubleOption = 1.123000"
+ }
+ };
+
private static final String[][] TYPE_1_ARGUMENTS = {
{
"-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1",
"-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption2",
"-XX:CompileCommand=option,com.oracle.Test::test,MyBoolOption3",
"-XX:CompileCommand=option,com/oracle/Test::test,MyBoolOption4",
- "-version"
- },
- {
- "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1,MyBoolOption2",
- "-version"
- },
- {
- "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption1,MyBoolOption2",
+ "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6",
+ "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8",
"-version"
}
};
private static final String[][] TYPE_1_EXPECTED_OUTPUTS = {
{
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption3 = true",
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption4 = true"
- },
- {
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
- },
- {
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true",
- "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption4 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true",
+ "CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true"
}
};
@@ -88,38 +122,28 @@
"-XX:CompileCommand=option,Test::test,intx,MyIntxOption,-1",
"-XX:CompileCommand=option,Test::test,uintx,MyUintxOption,1",
"-XX:CompileCommand=option,Test::test,MyFlag",
- "-XX:CompileCommand=option,Test::test,double,MyDoubleOption,1.123",
- "-version"
- },
- {
- "-XX:CompileCommand=option,Test.test,double,MyDoubleOption,1.123",
- "-version"
- },
- {
- "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx,MyIntxOption,-1,uintx,MyUintxOption,1,MyFlag,double,MyDoubleOption,1.123",
+ "-XX:CompileCommand=option,Test::test,double,MyDoubleOption1,1.123",
+ "-XX:CompileCommand=option,Test.test,double,MyDoubleOption2,1.123",
+ "-XX:CompileCommand=option,Test::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123",
"-version"
}
};
private static final String[][] TYPE_2_EXPECTED_OUTPUTS = {
{
- "CompilerOracle: option Test.test const char* MyListOption = '_foo _bar'",
- "CompilerOracle: option Test.test const char* MyStrOption = '_foo'",
- "CompilerOracle: option Test.test bool MyBoolOption = false",
- "CompilerOracle: option Test.test intx MyIntxOption = -1",
- "CompilerOracle: option Test.test uintx MyUintxOption = 1",
- "CompilerOracle: option Test.test bool MyFlag = true",
- "CompilerOracle: option Test.test double MyDoubleOption = 1.123000"
- },
- {
- "CompilerOracle: option Test.test double MyDoubleOption = 1.123000"
- },
- {
- "CompilerOracle: option Test.test bool MyBoolOption = false",
- "CompilerOracle: option Test.test intx MyIntxOption = -1",
- "CompilerOracle: option Test.test uintx MyUintxOption = 1",
- "CompilerOracle: option Test.test bool MyFlag = true",
- "CompilerOracle: option Test.test double MyDoubleOption = 1.123000",
+ "CompileCommand: option Test.test const char* MyListOption = '_foo _bar'",
+ "CompileCommand: option Test.test const char* MyStrOption = '_foo'",
+ "CompileCommand: option Test.test bool MyBoolOption = false",
+ "CompileCommand: option Test.test intx MyIntxOption = -1",
+ "CompileCommand: option Test.test uintx MyUintxOption = 1",
+ "CompileCommand: option Test.test bool MyFlag = true",
+ "CompileCommand: option Test.test double MyDoubleOption1 = 1.123000",
+ "CompileCommand: option Test.test double MyDoubleOption2 = 1.123000",
+ "CompileCommand: option Test.test bool MyBoolOptionX = false",
+ "CompileCommand: option Test.test intx MyIntxOptionX = -1",
+ "CompileCommand: option Test.test uintx MyUintxOptionX = 1",
+ "CompileCommand: option Test.test bool MyFlagX = true",
+ "CompileCommand: option Test.test double MyDoubleOptionX = 1.123000",
}
};
@@ -172,7 +196,7 @@
out.shouldContain(expected_output);
}
- out.shouldNotContain("CompileCommand: unrecognized line");
+ out.shouldNotContain("CompileCommand: An error occured during parsing");
out.shouldHaveExitValue(0);
}
@@ -183,7 +207,7 @@
pb = ProcessTools.createJavaProcessBuilder(arguments);
out = new OutputAnalyzer(pb.start());
- out.shouldContain("CompileCommand: unrecognized line");
+ out.shouldContain("CompileCommand: An error occured during parsing");
out.shouldHaveExitValue(0);
}
@@ -212,5 +236,10 @@
for (String[] arguments: TYPE_2_INVALID_ARGUMENTS) {
verifyInvalidOption(arguments);
}
+
+ // Check if commands in command file are parsed correctly
+ for (int i = 0; i < FILE_ARGUMENTS.length; i++) {
+ verifyValidOption(FILE_ARGUMENTS[i], FILE_EXPECTED_OUTPUT[i]);
+ }
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/oracle/TestCompileCommand.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.PrintWriter;
+import java.io.File;
+
+import com.oracle.java.testlibrary.*;
+
+/*
+ * @test TestCompileCommand
+ * @bug 8069389
+ * @summary "Regression tests of -XX:CompileCommand"
+ * @library /testlibrary
+ * @run main TestCompileCommand
+ */
+
+public class TestCompileCommand {
+
+ private static final String[][] ARGUMENTS = {
+ {
+ "-XX:CompileCommand=print,*01234567890123456789012345678901234567890123456789,*0123456789012345678901234567890123456789",
+ "-version"
+ }
+ };
+
+ private static final String[][] OUTPUTS = {
+ {
+ "print *01234567890123456789012345678901234567890123456789.*0123456789012345678901234567890123456789"
+ }
+ };
+
+ private static void verifyValidOption(String[] arguments, String[] expected_outputs) throws Exception {
+ ProcessBuilder pb;
+ OutputAnalyzer out;
+
+ pb = ProcessTools.createJavaProcessBuilder(arguments);
+ out = new OutputAnalyzer(pb.start());
+
+ for (String expected_output : expected_outputs) {
+ out.shouldContain(expected_output);
+ }
+
+ out.shouldNotContain("CompileCommand: An error occured during parsing");
+ out.shouldHaveExitValue(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ if (ARGUMENTS.length != OUTPUTS.length) {
+ throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (1) options does not match.");
+ }
+
+ // Check if type (1) options are parsed correctly
+ for (int i = 0; i < ARGUMENTS.length; i++) {
+ verifyValidOption(ARGUMENTS[i], OUTPUTS[i]);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/oracle/command1.txt Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,12 @@
+option,com/oracle/Test.test,MyBoolOption1
+option,com/oracle/Test,test,MyBoolOption2
+option,com.oracle.Test::test,MyBoolOption3
+option,com/oracle/Test::test,MyBoolOption4
+option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6
+option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8
+option,com/oracle/Test.test(I),MyBoolOption9
+option,com/oracle/Test,test,(I),MyBoolOption10
+option,com.oracle.Test::test(I),MyBoolOption11
+option,com/oracle/Test::test(I),MyBoolOption12
+option,com/oracle/Test.test(I),MyBoolOption13,MyBoolOption14
+option,com/oracle/Test,test(I),MyBoolOption15,MyBoolOption16
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/oracle/command2.txt Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,7 @@
+option,Test::test,ccstrlist,MyListOption,_foo,_bar
+option,Test::test,ccstr,MyStrOption,_foo
+option,Test::test,bool,MyBoolOption,false
+option,Test::test,intx,MyIntxOption,-1
+option,Test::test,uintx,MyUintxOption,1
+option,Test::test,MyFlag
+option,Test::test,double,MyDoubleOption,1.123
--- a/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass/Launcher.java Mon Feb 09 09:52:48 2015 -0800
@@ -28,7 +28,6 @@
* @bug 8038636
* @library /testlibrary
* @build Agent
- * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/profiling/spectrapredefineclass_classloaders/Launcher.java Mon Feb 09 09:52:48 2015 -0800
@@ -28,7 +28,6 @@
* @bug 8040237
* @library /testlibrary
* @build Agent Test A B
- * @ignore 7076820
* @run main ClassFileInstaller Agent
* @run main Launcher
* @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement -XX:TypeProfileLevel=222 -XX:ReservedCodeCacheSize=3M Agent
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -119,13 +119,13 @@
return new String[] { getMethodWithLockName() };
}
- public void lock(booleab forceAbort) {
+ public void lock(boolean forceAbort) {
synchronized(monitor) {
if (forceAbort) {
// We're calling native method in order to force
// abort. It's done by explicit xabort call emitted
// in SharedRuntime::generate_native_wrapper.
- // If an actuall JNI call will be replaced by
+ // If an actual JNI call will be replaced by
// intrinsic - we'll be in trouble, since xabort
// will be no longer called and test may fail.
UNSAFE.addressSize();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/stringopts/TestOptimizeStringConcat.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 SAP AG. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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 8068909
+ * @key regression
+ * @summary test that string optimizations produce code, that doesn't lead to a crash.
+ * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestOptimizeStringConcat
+ * @author axel.siebenborn@sap.com
+ */
+public class TestOptimizeStringConcat {
+
+ static boolean checkArgumentSyntax(String value, String allowedchars, String notallowedchars, String logmsg) {
+ String rc = null;
+
+ int maxchar = 99999;
+ int minchar = 1;
+ if ((allowedchars != null && notallowedchars != null) || minchar > maxchar) {
+ rc = "internal error";
+ } else {
+ if (value == null) {
+ rc = "the value null is not allowed, it is missing";
+ } else if (value != null && minchar > 0 && value.trim().equals("")) {
+ rc = "the value must not be empty";
+ } else if (value != null) {
+ if (value.length() < minchar || value.length() > maxchar) {
+ if (rc == null) {
+ rc = "the value length must be between +minchar+ and +maxchar";
+ }
+ }
+ char[] _value = value.toCharArray();
+ boolean dotfound = false;
+ int i = 1;
+ if (_value[i] == '.' && !dotfound) {
+ dotfound = true;
+ } else if (allowedchars != null && allowedchars.indexOf(_value[i]) == -1) {
+ if (rc == null) {
+ rc = "the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+ } else {
+ rc += " / the value contains an illegal character: '" + _value[i] + "', only following characters are allowed: '+allowedchars+'";
+ }
+ } else if (notallowedchars != null && notallowedchars.indexOf(_value[i]) != -1) {
+ if (rc == null) {
+ rc = "the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+ } else {
+ rc += " / the value contains an illegal character: '" + _value[i] + "', following characters are not allowed '+notallowedchars+'";
+ }
+ }
+ }
+ }
+
+ if (rc != null) {
+ System.out.println(logmsg + " ==> " + rc);
+ return false;
+ }
+ return true;
+ }
+
+ public static void main(String[] args) {
+ boolean failed = false;
+ for (int i = 0; i < 10000; i++) {
+ failed |= !checkArgumentSyntax("theName", null, "\"<&", "Error consistencyCheck: name in component definition");
+ failed |= !checkArgumentSyntax(null, null, "\"<&", "Error consistencyCheck: name in component definition");
+ failed |= !checkArgumentSyntax("42", "0123456789.", null, "Error consistencyCheck: counter in component definition");
+ }
+ System.out.println(failed);
+ }
+}
--- a/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/testlibrary/rtm/BusyLock.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,6 @@
package rtm;
-import com.oracle.java.testlibrary.Utils;
-import sun.misc.Unsafe;
-
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
@@ -42,7 +39,6 @@
// Following field have to be static in order to avoid escape analysis.
@SuppressWarnings("UnsuedDeclaration")
private static int field = 0;
- private static final Unsafe UNSAFE = Utils.getUnsafe();
protected final Object monitor;
protected final int timeout;
@@ -59,18 +55,9 @@
@Override
public void run() {
try {
- // wait until forceAbort leave monitor
- barrier.await();
- if (UNSAFE.tryMonitorEnter(monitor)) {
- try {
- barrier.await();
- Thread.sleep(timeout);
- } finally {
- UNSAFE.monitorExit(monitor);
- }
- } else {
- throw new RuntimeException("Monitor should be entered by " +
- "::run() first.");
+ synchronized (monitor) {
+ barrier.await();
+ Thread.sleep(timeout);
}
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException("Synchronization error happened.", e);
@@ -79,7 +66,6 @@
public void syncAndTest() {
try {
- barrier.await();
// wait until monitor is locked by a ::run method
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
--- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -34,7 +34,6 @@
/*
* @test
* @bug 8059624 8064669
- * @ignore 8066998
* @library /testlibrary /../../test/lib
* @build ForceNMethodSweepTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
@@ -42,7 +41,7 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:-TieredCompilation -XX:+WhiteBoxAPI
* -XX:CompileCommand=compileonly,SimpleTestCase$Helper::*
- * ForceNMethodSweepTest
+ * -XX:-BackgroundCompilation ForceNMethodSweepTest
* @summary testing of WB::forceNMethodSweep
*/
public class ForceNMethodSweepTest extends CompilerWhiteBoxTest {
--- a/hotspot/test/gc/TestNUMAPageSize.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/gc/TestNUMAPageSize.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,6 +25,7 @@
* @test TestNUMAPageSize
* @summary Make sure that start up with NUMA support does not cause problems.
* @bug 8061467
+ * @requires (vm.opt.AggressiveOpts == null) | (vm.opt.AggressiveOpts == false)
* @key gc
* @key regression
* @run main/othervm -Xmx8M -XX:+UseNUMA TestNUMAPageSize
--- a/hotspot/test/gc/TestSmallHeap.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/gc/TestSmallHeap.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,6 +25,7 @@
* @test TestSmallHeap
* @bug 8067438
* @requires vm.gc=="null"
+ * @requires (vm.opt.AggressiveOpts=="null") | (vm.opt.AggressiveOpts=="false")
* @summary Verify that starting the VM with a small heap works
* @library /testlibrary /../../test/lib
* @build TestSmallHeap
@@ -33,8 +34,9 @@
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseSerialGC TestSmallHeap
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseG1GC TestSmallHeap
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmx2m -XX:+UseConcMarkSweepGC TestSmallHeap
- *
- * Note: It would be nice to verify the minimal supported heap size (2m) here,
+ */
+
+/* Note: It would be nice to verify the minimal supported heap size (2m) here,
* but we align the heap size based on the card table size. And the card table
* size is aligned based on the minimal pages size provided by the os. This
* means that on most platforms, where the minimal page size is 4k, we get a
--- a/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/gc/g1/TestHumongousCodeCacheRoots.java Mon Feb 09 09:52:48 2015 -0800
@@ -116,7 +116,14 @@
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0]));
OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldHaveExitValue(0);
+ try {
+ output.shouldHaveExitValue(0);
+ } catch (RuntimeException e) {
+ // It's ok if there is no client vm in the jdk.
+ if (output.firstMatch("Unrecognized option: -client") == null) {
+ throw e;
+ }
+ }
return output;
}
--- a/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java Mon Feb 09 09:52:48 2015 -0800
@@ -41,6 +41,10 @@
// Compressed Class Space is only available on 64-bit JVMs
return;
}
+ if (!Platform.shouldSAAttach()) {
+ System.out.println("SA attach not expected to work - test skipped.");
+ return;
+ }
String pid = Integer.toString(ProcessTools.getProcessId());
--- a/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/runtime/ErrorHandling/ProblematicFrameTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
public static void main(String[] args) throws Exception {
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
- "-Xmx64m", "-XX:-TransmitErrorReport", Crasher.class.getName());
+ "-Xmx64m", "-XX:-TransmitErrorReport", "-XX:-CreateMinidumpOnCrash", Crasher.class.getName());
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldNotMatch("error occurred during error reporting \\(printing problematic frame\\)");
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/AllocateInstance.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 Verifies the behaviour of Unsafe.allocateInstance
+ * @library /testlibrary
+ * @run main AllocateInstance
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class AllocateInstance {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+
+ // allocateInstance() should not result in a call to the constructor
+ TestClass tc = (TestClass)unsafe.allocateInstance(TestClass.class);
+ assertFalse(tc.calledConstructor);
+
+ // allocateInstance() on an abstract class should result in an InstantiationException
+ try {
+ AbstractClass ac = (AbstractClass)unsafe.allocateInstance(AbstractClass.class);
+ throw new RuntimeException("Did not get expected InstantiationException");
+ } catch (InstantiationException e) {
+ // Expected
+ }
+ }
+
+ class TestClass {
+ public boolean calledConstructor = false;
+
+ public TestClass() {
+ calledConstructor = true;
+ }
+ }
+
+ abstract class AbstractClass {
+ public AbstractClass() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/AllocateMemory.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies behaviour of Unsafe.allocateMemory
+ * @library /testlibrary
+ * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:MallocMaxTestWords=20m AllocateMemory
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class AllocateMemory {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+
+ // Allocate a byte, write to the location and read back the value
+ long address = unsafe.allocateMemory(1);
+ assertNotEquals(address, 0L);
+
+ unsafe.putByte(address, Byte.MAX_VALUE);
+ assertEquals(Byte.MAX_VALUE, unsafe.getByte(address));
+ unsafe.freeMemory(address);
+
+ // Call to allocateMemory() with a negative value should result in an IllegalArgumentException
+ try {
+ address = unsafe.allocateMemory(-1);
+ throw new RuntimeException("Did not get expected IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ assertNotEquals(address, 0L);
+ }
+
+ // allocateMemory() should throw an OutOfMemoryError when the underlying malloc fails,
+ // we test this by limiting the malloc using -XX:MallocMaxTestWords
+ try {
+ address = unsafe.allocateMemory(20 * 1024 * 1024 * 8);
+ } catch (OutOfMemoryError e) {
+ // Expected
+ return;
+ }
+ throw new RuntimeException("Did not get expected OutOfMemoryError");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/CopyMemory.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies behaviour of Unsafe.copyMemory
+ * @library /testlibrary
+ * @run main CopyMemory
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class CopyMemory {
+ final static int LENGTH = 8;
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ long src = unsafe.allocateMemory(LENGTH);
+ long dst = unsafe.allocateMemory(LENGTH);
+ assertNotEquals(src, 0L);
+ assertNotEquals(dst, 0L);
+
+ // call copyMemory() with different lengths and verify the contents of
+ // the destination array
+ for (int i = 0; i < LENGTH; i++) {
+ unsafe.putByte(src + i, (byte)i);
+ unsafe.copyMemory(src, dst, i);
+ for (int j = 0; j < i; j++) {
+ assertEquals(unsafe.getByte(src + j), unsafe.getByte(src + j));
+ }
+ }
+ unsafe.freeMemory(src);
+ unsafe.freeMemory(dst);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/DefineClass.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies the behaviour of Unsafe.defineClass
+ * @library /testlibrary
+ * @run main DefineClass
+ */
+
+import java.security.ProtectionDomain;
+import java.io.InputStream;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class DefineClass {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ TestClassLoader classloader = new TestClassLoader();
+ ProtectionDomain pd = new ProtectionDomain(null, null);
+
+ byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass", "class TestClass { }");
+
+ // Invalid class data
+ try {
+ unsafe.defineClass(null, klassbuf, 4, klassbuf.length - 4, classloader, pd);
+ throw new RuntimeException("defineClass did not throw expected ClassFormatError");
+ } catch (ClassFormatError e) {
+ // Expected
+ }
+
+ // Negative offset
+ try {
+ unsafe.defineClass(null, klassbuf, -1, klassbuf.length, classloader, pd);
+ throw new RuntimeException("defineClass did not throw expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ // Negative length
+ try {
+ unsafe.defineClass(null, klassbuf, 0, -1, classloader, pd);
+ throw new RuntimeException("defineClass did not throw expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ // Offset greater than klassbuf.length
+ try {
+ unsafe.defineClass(null, klassbuf, klassbuf.length + 1, klassbuf.length, classloader, pd);
+ throw new RuntimeException("defineClass did not throw expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ // Length greater than klassbuf.length
+ try {
+ unsafe.defineClass(null, klassbuf, 0, klassbuf.length + 1, classloader, pd);
+ throw new RuntimeException("defineClass did not throw expected IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+
+ Class klass = unsafe.defineClass(null, klassbuf, 0, klassbuf.length, classloader, pd);
+ assertEquals(klass.getClassLoader(), classloader);
+ assertEquals(klass.getProtectionDomain(), pd);
+ }
+
+ private static class TestClassLoader extends ClassLoader {
+ public TestClassLoader(ClassLoader parent) {
+ super(parent);
+ }
+
+ public TestClassLoader() {
+ super();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/FieldOffset.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies the behaviour of Unsafe.fieldOffset
+ * @library /testlibrary
+ * @run main FieldOffset
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class FieldOffset {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Field fields[] = Test.class.getDeclaredFields();
+
+ for (int i = 0; i < fields.length; i++) {
+ int offset = unsafe.fieldOffset(fields[i]);
+ // Ensure we got a valid offset value back
+ assertNotEquals(offset, unsafe.INVALID_FIELD_OFFSET);
+
+ // Make sure the field offset is unique
+ for (int j = 0; j < i; j++) {
+ assertNotEquals(offset, unsafe.fieldOffset(fields[j]));
+ }
+ }
+ }
+
+ class Test {
+ boolean booleanField;
+ byte byteField;
+ char charField;
+ double doubleField;
+ float floatField;
+ int intField;
+ long longField;
+ Object objectField;
+ short shortField;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetField.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies behaviour of Unsafe.getField
+ * @library /testlibrary
+ * @run main GetField
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import java.lang.reflect.*;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetField {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ // Unsafe.INVALID_FIELD_OFFSET is a static final int field,
+ // make sure getField returns the correct field
+ Field field = Unsafe.class.getField("INVALID_FIELD_OFFSET");
+ assertNotEquals(field.getModifiers() & Modifier.FINAL, 0);
+ assertNotEquals(field.getModifiers() & Modifier.STATIC, 0);
+ assertEquals(field.getType(), int.class);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutAddress.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * Verify behaviour of Unsafe.get/putAddress and Unsafe.addressSize
+ * @library /testlibrary
+ * @run main GetPutAddress
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutAddress {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ int addressSize = unsafe.addressSize();
+ // Ensure the size returned from Unsafe.addressSize is correct
+ assertEquals(unsafe.addressSize(), Platform.is32bit() ? 4 : 8);
+
+ // Write the address, read it back and make sure it's the same value
+ long address = unsafe.allocateMemory(addressSize);
+ unsafe.putAddress(address, address);
+ long readAddress = unsafe.getAddress(address);
+ if (addressSize == 4) {
+ readAddress &= 0x00000000FFFFFFFFL;
+ }
+ assertEquals(address, readAddress);
+ unsafe.freeMemory(address);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutBoolean.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putBoolean
+ * @library /testlibrary
+ * @run main GetPutBoolean
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutBoolean {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("b1");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(false, unsafe.getBoolean(t, offset));
+ unsafe.putBoolean(t, offset, true);
+ assertEquals(true, unsafe.getBoolean(t, offset));
+
+ boolean arrayBoolean[] = { true, false, false, true };
+ int scale = unsafe.arrayIndexScale(arrayBoolean.getClass());
+ offset = unsafe.arrayBaseOffset(arrayBoolean.getClass());
+ for (int i = 0; i < arrayBoolean.length; i++) {
+ assertEquals(unsafe.getBoolean(arrayBoolean, offset), arrayBoolean[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public boolean b1 = false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutByte.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putByte
+ * @library /testlibrary
+ * @run main GetPutByte
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutByte {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("b");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals((byte)0, unsafe.getByte(t, offset));
+ unsafe.putByte(t, offset, (byte)1);
+ assertEquals((byte)1, unsafe.getByte(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putByte(address, (byte)2);
+ assertEquals((byte)2, unsafe.getByte(address));
+ unsafe.freeMemory(address);
+
+ byte arrayByte[] = { -1, 0, 1, 2 };
+ int scale = unsafe.arrayIndexScale(arrayByte.getClass());
+ offset = unsafe.arrayBaseOffset(arrayByte.getClass());
+ for (int i = 0; i < arrayByte.length; i++) {
+ assertEquals(unsafe.getByte(arrayByte, offset), arrayByte[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public byte b = 0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutChar.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putChar
+ * @library /testlibrary
+ * @run main GetPutChar
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutChar {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("c");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals('\u0000', unsafe.getChar(t, offset));
+ unsafe.putChar(t, offset, '\u0001');
+ assertEquals('\u0001', unsafe.getChar(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putChar(address, '\u0002');
+ assertEquals('\u0002', unsafe.getChar(address));
+ unsafe.freeMemory(address);
+
+ char arrayChar[] = { '\uabcd', '\u00ff', '\uff00', };
+ int scale = unsafe.arrayIndexScale(arrayChar.getClass());
+ offset = unsafe.arrayBaseOffset(arrayChar.getClass());
+ for (int i = 0; i < arrayChar.length; i++) {
+ assertEquals(unsafe.getChar(arrayChar, offset), arrayChar[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public char c = '\u0000';
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutDouble.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putDouble
+ * @library /testlibrary
+ * @run main GetPutDouble
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutDouble {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("d");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(-1.0, unsafe.getDouble(t, offset));
+ unsafe.putDouble(t, offset, 0.0);
+ assertEquals(0.0, unsafe.getDouble(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putDouble(address, 1.0);
+ assertEquals(1.0, unsafe.getDouble(address));
+ unsafe.freeMemory(address);
+
+ double arrayDouble[] = { -1.0, 0.0, 1.0, 2.0 };
+ int scale = unsafe.arrayIndexScale(arrayDouble.getClass());
+ offset = unsafe.arrayBaseOffset(arrayDouble.getClass());
+ for (int i = 0; i < arrayDouble.length; i++) {
+ assertEquals(unsafe.getDouble(arrayDouble, offset), arrayDouble[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public double d = -1.0;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutFloat.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putFloat
+ * @library /testlibrary
+ * @run main GetPutFloat
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutFloat {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("f");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(-1.0f, unsafe.getFloat(t, offset));
+ unsafe.putFloat(t, offset, 0.0f);
+ assertEquals(0.0f, unsafe.getFloat(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putFloat(address, 1.0f);
+ assertEquals(1.0f, unsafe.getFloat(address));
+ unsafe.freeMemory(address);
+
+ float arrayFloat[] = { -1.0f, 0.0f, 1.0f, 2.0f };
+ int scale = unsafe.arrayIndexScale(arrayFloat.getClass());
+ offset = unsafe.arrayBaseOffset(arrayFloat.getClass());
+ for (int i = 0; i < arrayFloat.length; i++) {
+ assertEquals(unsafe.getFloat(arrayFloat, offset), arrayFloat[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public float f = -1.0f;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutInt.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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
+ * @library /testlibrary
+ * @run main GetPutInt
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutInt {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("i");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(-1, unsafe.getInt(t, offset));
+ unsafe.putInt(t, offset, 0);
+ assertEquals(0, unsafe.getInt(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putInt(address, 1);
+ assertEquals(1, unsafe.getInt(address));
+ unsafe.freeMemory(address);
+
+ int arrayInt[] = { -1, 0, 1, 2 };
+ int scale = unsafe.arrayIndexScale(arrayInt.getClass());
+ offset = unsafe.arrayBaseOffset(arrayInt.getClass());
+ for (int i = 0; i < arrayInt.length; i++) {
+ assertEquals(unsafe.getInt(arrayInt, offset), arrayInt[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public int i = -1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutLong.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putLong
+ * @library /testlibrary
+ * @run main GetPutLong
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutLong {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("l");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(-1L, unsafe.getLong(t, offset));
+ unsafe.putLong(t, offset, 0L);
+ assertEquals(0L, unsafe.getLong(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putLong(address, 1L);
+ assertEquals(1L, unsafe.getLong(address));
+ unsafe.freeMemory(address);
+
+ long arrayLong[] = { -1, 0, 1, 2 };
+ int scale = unsafe.arrayIndexScale(arrayLong.getClass());
+ offset = unsafe.arrayBaseOffset(arrayLong.getClass());
+ for (int i = 0; i < arrayLong.length; i++) {
+ assertEquals(unsafe.getLong(arrayLong, offset), arrayLong[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public long l = -1L;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutObject.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putObject
+ * @library /testlibrary
+ * @run main GetPutObject
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutObject {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Object o = new Object();
+ Field field = Test.class.getField("o");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals(t.o, unsafe.getObject(t, offset));
+
+ unsafe.putObject(t, offset, o);
+ assertEquals(o, unsafe.getObject(t, offset));
+
+ Object arrayObject[] = { unsafe, null, new Object() };
+ int scale = unsafe.arrayIndexScale(arrayObject.getClass());
+ offset = unsafe.arrayBaseOffset(arrayObject.getClass());
+ for (int i = 0; i < arrayObject.length; i++) {
+ assertEquals(unsafe.getObject(arrayObject, offset), arrayObject[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public Object o = new Object();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetPutShort.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify behaviour of Unsafe.get/putShort
+ * @library /testlibrary
+ * @run main GetPutShort
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetPutShort {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ Test t = new Test();
+ Field field = Test.class.getField("s");
+
+ int offset = unsafe.fieldOffset(field);
+ assertEquals((short)-1, unsafe.getShort(t, offset));
+ unsafe.putShort(t, offset, (short)0);
+ assertEquals((short)0, unsafe.getShort(t, offset));
+
+ long address = unsafe.allocateMemory(8);
+ unsafe.putShort(address, (short)1);
+ assertEquals((short)1, unsafe.getShort(address));
+ unsafe.freeMemory(address);
+
+ short arrayShort[] = { -1, 0, 1, 2 };
+ int scale = unsafe.arrayIndexScale(arrayShort.getClass());
+ offset = unsafe.arrayBaseOffset(arrayShort.getClass());
+ for (int i = 0; i < arrayShort.length; i++) {
+ assertEquals(unsafe.getShort(arrayShort, offset), arrayShort[i]);
+ offset += scale;
+ }
+ }
+
+ static class Test {
+ public short s = -1;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/GetUnsafe.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies that getUnsafe() actually throws SecurityException when unsafeAccess is prohibited.
+ * @library /testlibrary
+ * @run main GetUnsafe
+ */
+
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class GetUnsafe {
+ public static void main(String args[]) throws Exception {
+ try {
+ Unsafe unsafe = Unsafe.getUnsafe();
+ } catch (SecurityException e) {
+ // Expected
+ return;
+ }
+ throw new RuntimeException("Did not get expected SecurityException");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/PageSize.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Make sure pageSize() returns a value that is a power of two
+ * @library /testlibrary
+ * @run main PageSize
+ */
+
+import java.lang.reflect.Field;
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class PageSize {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ int pageSize = unsafe.pageSize();
+
+ for (int n = 1; n != 0; n <<= 1) {
+ if (pageSize == n) {
+ return;
+ }
+ }
+ throw new RuntimeException("Expected pagesize to be a power of two, actual pagesize:" + pageSize);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/SetMemory.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verifies that setMemory works correctly
+ * @library /testlibrary
+ * @run main SetMemory
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class SetMemory {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ long address = unsafe.allocateMemory(1);
+ assertNotEquals(address, 0L);
+ unsafe.setMemory(address, 1, (byte)17);
+ assertEquals((byte)17, unsafe.getByte(address));
+ unsafe.freeMemory(address);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Unsafe/ThrowException.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Verify that throwException() can throw an exception
+ * @library /testlibrary
+ * @run main ThrowException
+ */
+
+import com.oracle.java.testlibrary.*;
+import sun.misc.Unsafe;
+import static com.oracle.java.testlibrary.Asserts.*;
+
+public class ThrowException {
+ public static void main(String args[]) throws Exception {
+ Unsafe unsafe = Utils.getUnsafe();
+ try {
+ unsafe.throwException(new TestException());
+ } catch (Throwable t) {
+ if (t instanceof TestException) {
+ return;
+ }
+ throw t;
+ }
+ throw new RuntimeException("Did not throw expected TestException");
+ }
+ static class TestException extends Exception {}
+}
--- a/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/hotspot/test/serviceability/dcmd/compiler/CompilerQueueTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,6 +25,7 @@
* @test CompilerQueueTest
* @bug 8054889
* @library ..
+ * @ignore 8069160
* @build DcmdUtil CompilerQueueTest
* @run main CompilerQueueTest
* @run main/othervm -XX:-TieredCompilation CompilerQueueTest
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/TestLambdaFormRetransformation.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,138 @@
+
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8008678
+ * @summary JSR 292: constant pool reconstitution must support pseudo strings
+ * @library /testlibrary
+ * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
+ * @run main TestLambdaFormRetransformation
+ */
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+
+import com.oracle.java.testlibrary.ExitCode;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+public class TestLambdaFormRetransformation {
+ private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
+ "Premain-Class: %s\n" +
+ "Can-Retransform-Classes: true\n",
+ Agent.class.getName());
+
+ private static String CP = System.getProperty("test.classes");
+
+ public static void main(String args[]) throws Throwable {
+ Path agent = TestLambdaFormRetransformation.buildAgent();
+ OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
+ agent.toAbsolutePath().toString(), "-version");
+ oa.shouldHaveExitValue(ExitCode.OK.value);
+ }
+
+ private static Path buildAgent() throws IOException {
+ Path manifest = TestLambdaFormRetransformation.createManifest();
+ Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+
+ String[] args = new String[] {
+ "-cfm",
+ jar.toAbsolutePath().toString(),
+ manifest.toAbsolutePath().toString(),
+ "-C",
+ TestLambdaFormRetransformation.CP,
+ Agent.class.getName() + ".class"
+ };
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+
+ if (!jarTool.run(args)) {
+ throw new Error("jar failed: args=" + Arrays.toString(args));
+ }
+ return jar;
+ }
+
+ private static Path createManifest() throws IOException {
+ Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
+ byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
+ Files.write(manifest, manifestBytes);
+ return manifest;
+ }
+}
+
+class Agent implements ClassFileTransformer {
+ private static Runnable lambda = () -> {
+ System.out.println("I'll crash you!");
+ };
+
+ public static void premain(String args, Instrumentation instrumentation) {
+ if (!instrumentation.isRetransformClassesSupported()) {
+ System.out.println("Class retransformation is not supported.");
+ return;
+ }
+ System.out.println("Calling lambda to ensure that lambda forms were created");
+
+ Agent.lambda.run();
+
+ System.out.println("Registering class file transformer");
+
+ instrumentation.addTransformer(new Agent());
+
+ for (Class c : instrumentation.getAllLoadedClasses()) {
+ if (c.getName().contains("LambdaForm") &&
+ instrumentation.isModifiableClass(c)) {
+ System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
+ try {
+ instrumentation.retransformClasses(c);
+ } catch (UnmodifiableClassException e) {
+ throw new AssertionError("Modification of modifiable class " +
+ "caused UnmodifiableClassException", e);
+ }
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ }
+
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) throws IllegalClassFormatException {
+ System.out.println("Transforming " + className);
+ return classfileBuffer.clone();
+ }
+}
--- a/jaxp/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
0dab3e848229127c7aca4c58b98e2d90ba70372f jdk9-b45
74eaf7ad986576c792df4dbff05eed63e5727695 jdk9-b46
e391de88e69b59d7c618387e3cf91032f6991ce9 jdk9-b47
+833051855168a973780fafeb6fc59e7370bcf400 jdk9-b48
+786058752e0ac3e48d7aef79e0885d29d6a2a7eb jdk9-b49
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Mon Feb 09 09:52:48 2015 -0800
@@ -270,8 +270,8 @@
if (Double.isNaN(start))
return(EMPTYSTRING);
- final int strlen = value.length();
- int istart = (int)Math.round(start) - 1;
+ final int strlen = value.length();
+ int istart = (int)Math.round(start) - 1;
if (istart > strlen)
return(EMPTYSTRING);
@@ -292,10 +292,11 @@
public static String substringF(String value, double start, double length) {
if (Double.isInfinite(start) ||
Double.isNaN(start) ||
- Double.isNaN(length))
+ Double.isNaN(length) ||
+ length < 0)
return(EMPTYSTRING);
- int istart = (int)Math.round(start) - 1;
+ int istart = (int)Math.round(start) - 1;
final int isum;
if (Double.isInfinite(length))
isum = Integer.MAX_VALUE;
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,15 +1,15 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * Copyright 1999-2004 The Apache Software Foundation.
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,36 +17,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// $Id: XPathExpressionImpl.java,v 1.3 2005/09/27 09:40:43 sunithareddy Exp $
package com.sun.org.apache.xpath.internal.jaxp;
-import com.sun.org.apache.xpath.internal.*;
-import javax.xml.transform.TransformerException;
-
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xml.internal.dtm.DTM;
-import com.sun.org.apache.xml.internal.utils.PrefixResolver;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xalan.internal.res.XSLMessages;
-import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
-import com.sun.org.apache.xalan.internal.utils.FeatureManager;
-
-import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
-import javax.xml.xpath.XPathConstants;
-
+import org.w3c.dom.Document;
import org.w3c.dom.Node;
-import org.w3c.dom.Document;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.traversal.NodeIterator;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.DocumentBuilder;
-
import org.xml.sax.InputSource;
/**
@@ -54,21 +39,9 @@
*
* @author Ramesh Mandava
*/
-public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{
-
- private XPathFunctionResolver functionResolver;
- private XPathVariableResolver variableResolver;
- private JAXPPrefixResolver prefixResolver;
- private com.sun.org.apache.xpath.internal.XPath xpath;
+public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression {
- // By default Extension Functions are allowed in XPath Expressions. If
- // Secure Processing Feature is set on XPathFactory then the invocation of
- // extensions function need to throw XPathFunctionException
- private boolean featureSecureProcessing = false;
-
- private boolean useServicesMechanism = true;
-
- private final FeatureManager featureManager;
+ private com.sun.org.apache.xpath.internal.XPath xpath;
/** Protected constructor to prevent direct instantiation; use compile()
* from the context.
@@ -81,7 +54,7 @@
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,
XPathFunctionResolver functionResolver,
- XPathVariableResolver variableResolver ) {
+ XPathVariableResolver variableResolver) {
this(xpath, prefixResolver, functionResolver, variableResolver,
false, true, new FeatureManager());
};
@@ -89,291 +62,108 @@
protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath,
JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver,
XPathVariableResolver variableResolver, boolean featureSecureProcessing,
- boolean useServicesMechanism, FeatureManager featureManager ) {
+ boolean useServiceMechanism, FeatureManager featureManager) {
this.xpath = xpath;
this.prefixResolver = prefixResolver;
this.functionResolver = functionResolver;
this.variableResolver = variableResolver;
this.featureSecureProcessing = featureSecureProcessing;
- this.useServicesMechanism = useServicesMechanism;
+ this.useServiceMechanism = useServiceMechanism;
this.featureManager = featureManager;
};
- public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath ) {
+ public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath) {
this.xpath = xpath;
}
public Object eval(Object item, QName returnType)
throws javax.xml.transform.TransformerException {
- XObject resultObject = eval ( item );
- return getResultAsType( resultObject, returnType );
- }
-
- private XObject eval ( Object contextItem )
- throws javax.xml.transform.TransformerException {
- com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
- if ( functionResolver != null ) {
- JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing, featureManager );
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
- } else {
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
- }
-
- xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
- XObject xobj = null;
-
- Node contextNode = (Node)contextItem;
- // We always need to have a ContextNode with Xalan XPath implementation
- // To allow simple expression evaluation like 1+1 we are setting
- // dummy Document as Context Node
-
- if ( contextNode == null )
- xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver);
- else
- xobj = xpath.execute(xpathSupport, contextNode, prefixResolver);
-
- return xobj;
+ XObject resultObject = eval(item, xpath);
+ return getResultAsType(resultObject, returnType);
}
-
- /**
- * <p>Evaluate the compiled XPath expression in the specified context and
- * return the result as the specified type.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined
- * in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param item The starting context (node or node list, for example).
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that is the result of evaluating the
- * expression and converting the result to
- * <code>returnType</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>returnType</code> is
- * <code>null</code>.
- */
+ @Override
public Object evaluate(Object item, QName returnType)
throws XPathExpressionException {
- //Validating parameters to enforce constraints defined by JAXP spec
- if ( returnType == null ) {
- //Throwing NullPointerException as defined in spec
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to be
- // defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported(returnType);
try {
- return eval( item, returnType);
- } catch ( java.lang.NullPointerException npe ) {
+ return eval(item, returnType);
+ } catch (java.lang.NullPointerException npe) {
// If VariableResolver returns null Or if we get
// NullPointerException at this stage for some other reason
// then we have to reurn XPathException
- throw new XPathExpressionException ( npe );
- } catch ( javax.xml.transform.TransformerException te ) {
+ throw new XPathExpressionException (npe);
+ } catch (javax.xml.transform.TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
// For any other exceptions we need to throw
- // XPathExpressionException ( as per spec )
- throw new XPathExpressionException( te);
+ // XPathExpressionException (as per spec)
+ throw new XPathExpressionException(te);
}
}
-
- }
-
- /**
- * <p>Evaluate the compiled XPath expression in the specified context and
- * return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(Object item, QName returnType)}
- * with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- *
- * @param item The starting context (node or node list, for example).
- *
- * @return The <code>String</code> that is the result of evaluating the
- * expression and converting the result to a
- * <code>String</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- */
- public String evaluate(Object item)
- throws XPathExpressionException {
- return (String)this.evaluate( item, XPathConstants.STRING );
}
-
- static DocumentBuilderFactory dbf = null;
- static DocumentBuilder db = null;
- static Document d = null;
+ @Override
+ public String evaluate(Object item)
+ throws XPathExpressionException {
+ return (String)this.evaluate(item, XPathConstants.STRING);
+ }
- /**
- * <p>Evaluate the compiled XPath expression in the context of the
- * specified <code>InputSource</code> and return the result as the
- * specified type.</p>
- *
- * <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(Object item, QName returnType)} on the resulting
- * document object.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in
- * {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- *<p>If <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param source The <code>InputSource</code> of the document to evaluate
- * over.
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that is the result of evaluating the
- * expression and converting the result to
- * <code>returnType</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>source</code> or
- * <code>returnType</code> is <code>null</code>.
- */
+ @Override
public Object evaluate(InputSource source, QName returnType)
throws XPathExpressionException {
- if ( ( source == null ) || ( returnType == null ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL,
- null );
- throw new NullPointerException ( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to be
- // defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported (returnType);
try {
- if ( dbf == null ) {
- dbf = FactoryImpl.getDOMFactory(useServicesMechanism);
- dbf.setNamespaceAware( true );
- dbf.setValidating( false );
- }
- db = dbf.newDocumentBuilder();
- Document document = db.parse( source );
- return eval( document, returnType );
- } catch ( Exception e ) {
- throw new XPathExpressionException ( e );
+ Document document = getDocument(source);
+ return eval(document, returnType);
+ } catch (TransformerException e) {
+ throw new XPathExpressionException(e);
}
}
- /**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a
- * <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param source The <code>InputSource</code> of the document to evaluate over.
- *
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws NullPointerException If <code>source</code> is <code>null</code>.
- */
+ @Override
public String evaluate(InputSource source)
throws XPathExpressionException {
- return (String)this.evaluate( source, XPathConstants.STRING );
+ return (String)this.evaluate(source, XPathConstants.STRING);
}
- private boolean isSupported( QName returnType ) {
- // XPathConstants.STRING
- if ( ( returnType.equals( XPathConstants.STRING ) ) ||
- ( returnType.equals( XPathConstants.NUMBER ) ) ||
- ( returnType.equals( XPathConstants.BOOLEAN ) ) ||
- ( returnType.equals( XPathConstants.NODE ) ) ||
- ( returnType.equals( XPathConstants.NODESET ) ) ) {
+ @Override
+ public <T>T evaluateExpression(Object item, Class<T> type)
+ throws XPathExpressionException {
+ isSupportedClassType(type);
- return true;
- }
- return false;
- }
+ try {
+ XObject resultObject = eval(item, xpath);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return getXPathResult(resultObject, type);
+ } else {
+ return XPathResultImpl.getValue(resultObject, type);
+ }
- private Object getResultAsType( XObject resultObject, QName returnType )
- throws javax.xml.transform.TransformerException {
- // XPathConstants.STRING
- if ( returnType.equals( XPathConstants.STRING ) ) {
- return resultObject.str();
+ } catch (javax.xml.transform.TransformerException te) {
+ throw new XPathExpressionException(te);
}
- // XPathConstants.NUMBER
- if ( returnType.equals( XPathConstants.NUMBER ) ) {
- return new Double ( resultObject.num());
- }
- // XPathConstants.BOOLEAN
- if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
- return new Boolean( resultObject.bool());
- }
- // XPathConstants.NODESET ---ORdered, UNOrdered???
- if ( returnType.equals( XPathConstants.NODESET ) ) {
- return resultObject.nodelist();
- }
- // XPathConstants.NODE
- if ( returnType.equals( XPathConstants.NODE ) ) {
- NodeIterator ni = resultObject.nodeset();
- //Return the first node, or null
- return ni.nextNode();
- }
- // If isSupported check is already done then the execution path
- // shouldn't come here. Being defensive
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString()});
- throw new IllegalArgumentException ( fmsg );
}
+ @Override
+ public XPathEvaluationResult<?> evaluateExpression(Object item)
+ throws XPathExpressionException {
+ return evaluateExpression(item, XPathEvaluationResult.class);
+ }
+
+ @Override
+ public <T>T evaluateExpression(InputSource source, Class<T> type)
+ throws XPathExpressionException {
+ Document document = getDocument(source);
+ return evaluateExpression(document, type);
+ }
+
+ @Override
+ public XPathEvaluationResult<?> evaluateExpression(InputSource source)
+ throws XPathExpressionException {
+ return evaluateExpression(source, XPathEvaluationResult.class);
+ }
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,6 +1,5 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Copyright 1999-2004 The Apache Software Foundation.
@@ -28,55 +27,37 @@
import javax.xml.xpath.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
import javax.xml.xpath.XPathExpression;
-
-import com.sun.org.apache.xml.internal.dtm.DTM;
import com.sun.org.apache.xpath.internal.*;
import com.sun.org.apache.xpath.internal.objects.XObject;
-import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
-import com.sun.org.apache.xalan.internal.res.XSLMessages;
-import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
import com.sun.org.apache.xalan.internal.utils.FeatureManager;
-
-import org.w3c.dom.Node;
import org.w3c.dom.Document;
-import org.w3c.dom.traversal.NodeIterator;
-
import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.*;
-
-import java.io.IOException;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathEvaluationResult;
/**
* The XPathImpl class provides implementation for the methods defined in
- * javax.xml.xpath.XPath interface. This provide simple access to the results
+ * javax.xml.xpath.XPath interface. This provides simple access to the results
* of an XPath expression.
*
- *
* @author Ramesh Mandava
+ *
+ * Updated 12/04/2014:
+ * New methods: evaluateExpression
+ * Refactored to share code with XPathExpressionImpl.
*/
-public class XPathImpl implements javax.xml.xpath.XPath {
+public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath {
// Private variables
- private XPathVariableResolver variableResolver;
- private XPathFunctionResolver functionResolver;
private XPathVariableResolver origVariableResolver;
private XPathFunctionResolver origFunctionResolver;
private NamespaceContext namespaceContext=null;
- private JAXPPrefixResolver prefixResolver;
- // By default Extension Functions are allowed in XPath Expressions. If
- // Secure Processing Feature is set on XPathFactory then the invocation of
- // extensions function need to throw XPathFunctionException
- private boolean featureSecureProcessing = false;
- private boolean useServiceMechanism = true;
- private final FeatureManager featureManager;
- XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) {
+ XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) {
this(vr, fr, false, true, new FeatureManager());
}
- XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr,
+ XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr,
boolean featureSecureProcessing, boolean useServiceMechanism,
FeatureManager featureManager) {
this.origVariableResolver = this.variableResolver = vr;
@@ -86,451 +67,173 @@
this.featureManager = featureManager;
}
- /**
- * <p>Establishes a variable resolver.</p>
- *
- * @param resolver Variable Resolver
- */
+
+ //-Override-
public void setXPathVariableResolver(XPathVariableResolver resolver) {
- if ( resolver == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPathVariableResolver"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(resolver, "XPathVariableResolver");
this.variableResolver = resolver;
}
- /**
- * <p>Returns the current variable resolver.</p>
- *
- * @return Current variable resolver
- */
+ //-Override-
public XPathVariableResolver getXPathVariableResolver() {
return variableResolver;
}
- /**
- * <p>Establishes a function resolver.</p>
- *
- * @param resolver XPath function resolver
- */
+ //-Override-
public void setXPathFunctionResolver(XPathFunctionResolver resolver) {
- if ( resolver == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPathFunctionResolver"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(resolver, "XPathFunctionResolver");
this.functionResolver = resolver;
}
- /**
- * <p>Returns the current function resolver.</p>
- *
- * @return Current function resolver
- */
+ //-Override-
public XPathFunctionResolver getXPathFunctionResolver() {
return functionResolver;
}
- /**
- * <p>Establishes a namespace context.</p>
- *
- * @param nsContext Namespace context to use
- */
+ //-Override-
public void setNamespaceContext(NamespaceContext nsContext) {
- if ( nsContext == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"NamespaceContext"} );
- throw new NullPointerException( fmsg );
- }
+ requireNonNull(nsContext, "NamespaceContext");
this.namespaceContext = nsContext;
- this.prefixResolver = new JAXPPrefixResolver ( nsContext );
+ this.prefixResolver = new JAXPPrefixResolver (nsContext);
}
- /**
- * <p>Returns the current namespace context.</p>
- *
- * @return Current Namespace context
- */
+ //-Override-
public NamespaceContext getNamespaceContext() {
return namespaceContext;
}
- private static Document d = null;
-
- private DocumentBuilder getParser() {
- try {
- // we'd really like to cache those DocumentBuilders, but we can't because:
- // 1. thread safety. parsers are not thread-safe, so at least
- // we need one instance per a thread.
- // 2. parsers are non-reentrant, so now we are looking at having a
- // pool of parsers.
- // 3. then the class loading issue. The look-up procedure of
- // DocumentBuilderFactory.newInstance() depends on context class loader
- // and system properties, which may change during the execution of JVM.
- //
- // so we really have to create a fresh DocumentBuilder every time we need one
- // - KK
- DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism);
- dbf.setNamespaceAware( true );
- dbf.setValidating( false );
- return dbf.newDocumentBuilder();
- } catch (ParserConfigurationException e) {
- // this should never happen with a well-behaving JAXP implementation.
- throw new Error(e);
- }
- }
-
+ /**
+ * Evaluate an {@code XPath} expression in the specified context.
+ * @param expression The XPath expression.
+ * @param contextItem The starting context.
+ * @return an XObject as the result of evaluating the expression
+ * @throws TransformerException if evaluating fails
+ */
+ private XObject eval(String expression, Object contextItem)
+ throws TransformerException {
+ requireNonNull(expression, "XPath expression");
+ com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression,
+ null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
- private XObject eval(String expression, Object contextItem)
- throws javax.xml.transform.TransformerException {
- com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression,
- null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
- com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null;
- if ( functionResolver != null ) {
- JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
- functionResolver, featureSecureProcessing, featureManager );
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep );
- } else {
- xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
- }
-
- XObject xobj = null;
-
- xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
-
- // If item is null, then we will create a a Dummy contextNode
- if ( contextItem instanceof Node ) {
- xobj = xpath.execute (xpathSupport, (Node)contextItem,
- prefixResolver );
- } else {
- xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver );
- }
-
- return xobj;
+ return eval(contextItem, xpath);
}
- /**
- * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and <code>QName</code> resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} (
- * {@link XPathConstants#NUMBER NUMBER},
- * {@link XPathConstants#STRING STRING},
- * {@link XPathConstants#BOOLEAN BOOLEAN},
- * {@link XPathConstants#NODE NODE} or
- * {@link XPathConstants#NODESET NODESET})
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (node or node list, for example).
- * @param returnType The desired return type.
- *
- * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>.
- */
+ //-Override-
public Object evaluate(String expression, Object item, QName returnType)
throws XPathExpressionException {
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
- if ( returnType == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException ( fmsg );
- }
- // Checking if requested returnType is supported. returnType need to
- // be defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ //this check is necessary before calling eval to maintain binary compatibility
+ requireNonNull(expression, "XPath expression");
+ isSupported(returnType);
try {
- XObject resultObject = eval( expression, item );
- return getResultAsType( resultObject, returnType );
- } catch ( java.lang.NullPointerException npe ) {
+ XObject resultObject = eval(expression, item);
+ return getResultAsType(resultObject, returnType);
+ } catch (java.lang.NullPointerException npe) {
// If VariableResolver returns null Or if we get
// NullPointerException at this stage for some other reason
// then we have to reurn XPathException
- throw new XPathExpressionException ( npe );
- } catch ( javax.xml.transform.TransformerException te ) {
+ throw new XPathExpressionException (npe);
+ } catch (TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
// For any other exceptions we need to throw
- // XPathExpressionException ( as per spec )
- throw new XPathExpressionException ( te );
+ // XPathExpressionException (as per spec)
+ throw new XPathExpressionException (te);
}
}
}
- private boolean isSupported( QName returnType ) {
- if ( ( returnType.equals( XPathConstants.STRING ) ) ||
- ( returnType.equals( XPathConstants.NUMBER ) ) ||
- ( returnType.equals( XPathConstants.BOOLEAN ) ) ||
- ( returnType.equals( XPathConstants.NODE ) ) ||
- ( returnType.equals( XPathConstants.NODESET ) ) ) {
-
- return true;
- }
- return false;
- }
-
- private Object getResultAsType( XObject resultObject, QName returnType )
- throws javax.xml.transform.TransformerException {
- // XPathConstants.STRING
- if ( returnType.equals( XPathConstants.STRING ) ) {
- return resultObject.str();
- }
- // XPathConstants.NUMBER
- if ( returnType.equals( XPathConstants.NUMBER ) ) {
- return new Double ( resultObject.num());
- }
- // XPathConstants.BOOLEAN
- if ( returnType.equals( XPathConstants.BOOLEAN ) ) {
- return new Boolean( resultObject.bool());
- }
- // XPathConstants.NODESET ---ORdered, UNOrdered???
- if ( returnType.equals( XPathConstants.NODESET ) ) {
- return resultObject.nodelist();
- }
- // XPathConstants.NODE
- if ( returnType.equals( XPathConstants.NODE ) ) {
- NodeIterator ni = resultObject.nodeset();
- //Return the first node, or null
- return ni.nextNode();
- }
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString()});
- throw new IllegalArgumentException( fmsg );
+ //-Override-
+ public String evaluate(String expression, Object item)
+ throws XPathExpressionException {
+ return (String)this.evaluate(expression, item, XPathConstants.STRING);
}
-
-
- /**
- * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (node or node list, for example).
- *
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
- */
- public String evaluate(String expression, Object item)
- throws XPathExpressionException {
- return (String)this.evaluate( expression, item, XPathConstants.STRING );
- }
-
- /**
- * <p>Compile an XPath expression for later evaluation.</p>
- *
- * <p>If <code>expression</code> contains any {@link XPathFunction}s,
- * they must be available via the {@link XPathFunctionResolver}.
- * An {@link XPathExpressionException} will be thrown if the <code>XPathFunction</code>
- * cannot be resovled with the <code>XPathFunctionResolver</code>.</p>
- *
- * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- *
- * @return Compiled XPath expression.
-
- * @throws XPathExpressionException If <code>expression</code> cannot be compiled.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
- */
+ //-Override-
public XPathExpression compile(String expression)
throws XPathExpressionException {
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
+ requireNonNull(expression, "XPath expression");
try {
com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null,
- prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT );
+ prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT);
// Can have errorListener
XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath,
prefixResolver, functionResolver, variableResolver,
- featureSecureProcessing, useServiceMechanism, featureManager );
+ featureSecureProcessing, useServiceMechanism, featureManager);
return ximpl;
- } catch ( javax.xml.transform.TransformerException te ) {
- throw new XPathExpressionException ( te ) ;
+ } catch (TransformerException te) {
+ throw new XPathExpressionException (te) ;
}
}
-
- /**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as the specified type.</p>
- *
- * <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param source The input source of the document to evaluate over.
- * @param returnType The desired return type.
- *
- * @return The <code>Object</code> that encapsulates the result of evaluating the expression.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code>
- * is <code>null</code>.
- */
+ //-Override-
public Object evaluate(String expression, InputSource source,
QName returnType) throws XPathExpressionException {
- // Checking validity of different parameters
- if( source== null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"source"} );
- throw new NullPointerException ( fmsg );
- }
- if ( expression == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"XPath expression"} );
- throw new NullPointerException ( fmsg );
- }
- if ( returnType == null ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
- new Object[] {"returnType"} );
- throw new NullPointerException ( fmsg );
- }
-
- //Checking if requested returnType is supported.
- //returnType need to be defined in XPathConstants
- if ( !isSupported ( returnType ) ) {
- String fmsg = XSLMessages.createXPATHMessage(
- XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
- new Object[] { returnType.toString() } );
- throw new IllegalArgumentException ( fmsg );
- }
+ isSupported(returnType);
try {
-
- Document document = getParser().parse( source );
-
- XObject resultObject = eval( expression, document );
- return getResultAsType( resultObject, returnType );
- } catch ( SAXException e ) {
- throw new XPathExpressionException ( e );
- } catch( IOException e ) {
- throw new XPathExpressionException ( e );
- } catch ( javax.xml.transform.TransformerException te ) {
+ Document document = getDocument(source);
+ XObject resultObject = eval(expression, document);
+ return getResultAsType(resultObject, returnType);
+ } catch (TransformerException te) {
Throwable nestedException = te.getException();
- if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) {
+ if (nestedException instanceof javax.xml.xpath.XPathFunctionException) {
throw (javax.xml.xpath.XPathFunctionException)nestedException;
} else {
- throw new XPathExpressionException ( te );
+ throw new XPathExpressionException (te);
}
}
-
}
-
-
-
- /**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as a <code>String</code>.</p>
- *
- * <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * <code>returnType</code> of {@link XPathConstants#STRING}.</p>
- *
- * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>expression</code> or <code>source</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param source The <code>InputSource</code> of the document to evaluate over.
- *
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>.
- */
+ //-Override-
public String evaluate(String expression, InputSource source)
throws XPathExpressionException {
- return (String)this.evaluate( expression, source, XPathConstants.STRING );
+ return (String)this.evaluate(expression, source, XPathConstants.STRING);
}
- /**
- * <p>Reset this <code>XPath</code> to its original configuration.</p>
- *
- * <p><code>XPath</code> is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s
- * thus saving resources associated with the creation of new <code>XPath</code>s.</p>
- *
- * <p>The reset <code>XPath</code> is not guaranteed to have the same
- * {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>,
- * <code>XPathVariableResolver</code>
- * and <code>NamespaceContext</code>.</p>
- */
+ //-Override-
public void reset() {
this.variableResolver = this.origVariableResolver;
this.functionResolver = this.origFunctionResolver;
this.namespaceContext = null;
}
+ //-Override-
+ public <T> T evaluateExpression(String expression, Object item, Class<T> type)
+ throws XPathExpressionException {
+ isSupportedClassType(type);
+ try {
+ XObject resultObject = eval(expression, item);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return getXPathResult(resultObject, type);
+ } else {
+ return XPathResultImpl.getValue(resultObject, type);
+ }
+ } catch (TransformerException te) {
+ throw new XPathExpressionException (te);
+ }
+ }
+
+ //-Override-
+ public XPathEvaluationResult<?> evaluateExpression(String expression, Object item)
+ throws XPathExpressionException {
+ return evaluateExpression(expression, item, XPathEvaluationResult.class);
+ }
+
+ //-Override-
+ public <T> T evaluateExpression(String expression, InputSource source, Class<T> type)
+ throws XPathExpressionException {
+ Document document = getDocument(source);
+ return evaluateExpression(expression, document, type);
+ }
+
+ //-Override-
+ public XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source)
+ throws XPathExpressionException {
+ return evaluateExpression(expression, source, XPathEvaluationResult.class);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import com.sun.org.apache.xalan.internal.res.XSLMessages;
+import com.sun.org.apache.xalan.internal.utils.FactoryImpl;
+import com.sun.org.apache.xalan.internal.utils.FeatureManager;
+import com.sun.org.apache.xml.internal.dtm.DTM;
+import com.sun.org.apache.xpath.internal.objects.XObject;
+import com.sun.org.apache.xpath.internal.res.XPATHErrorResources;
+import java.io.IOException;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFunctionResolver;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathVariableResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.traversal.NodeIterator;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * This class contains several utility methods used by XPathImpl and
+ * XPathExpressionImpl
+ */
+class XPathImplUtil {
+ XPathFunctionResolver functionResolver;
+ XPathVariableResolver variableResolver;
+ JAXPPrefixResolver prefixResolver;
+ boolean useServiceMechanism = true;
+ // By default Extension Functions are allowed in XPath Expressions. If
+ // Secure Processing Feature is set on XPathFactory then the invocation of
+ // extensions function need to throw XPathFunctionException
+ boolean featureSecureProcessing = false;
+ FeatureManager featureManager;
+
+ /**
+ * Evaluate an XPath context using the internal XPath engine
+ * @param contextItem The XPath context
+ * @param xpath The internal XPath engine
+ * @return an XObject
+ * @throws javax.xml.transform.TransformerException If the expression cannot be evaluated.
+ */
+ XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath)
+ throws javax.xml.transform.TransformerException {
+ com.sun.org.apache.xpath.internal.XPathContext xpathSupport;
+ if (functionResolver != null) {
+ JAXPExtensionsProvider jep = new JAXPExtensionsProvider(
+ functionResolver, featureSecureProcessing, featureManager);
+ xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(jep);
+ } else {
+ xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();
+ }
+
+ xpathSupport.setVarStack(new JAXPVariableStack(variableResolver));
+ XObject xobj;
+
+ Node contextNode = (Node)contextItem;
+ // We always need to have a ContextNode with Xalan XPath implementation
+ // To allow simple expression evaluation like 1+1 we are setting
+ // dummy Document as Context Node
+ if (contextNode == null) {
+ xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver);
+ } else {
+ xobj = xpath.execute(xpathSupport, contextNode, prefixResolver);
+ }
+
+ return xobj;
+ }
+
+ /**
+ * Parse the input source and return a Document.
+ * @param source The {@code InputSource} of the document
+ * @return a DOM Document
+ * @throws XPathExpressionException if there is an error parsing the source.
+ */
+ Document getDocument(InputSource source)
+ throws XPathExpressionException {
+ requireNonNull(source, "Source");
+ try {
+ // we'd really like to cache those DocumentBuilders, but we can't because:
+ // 1. thread safety. parsers are not thread-safe, so at least
+ // we need one instance per a thread.
+ // 2. parsers are non-reentrant, so now we are looking at having a
+ // pool of parsers.
+ // 3. then the class loading issue. The look-up procedure of
+ // DocumentBuilderFactory.newInstance() depends on context class loader
+ // and system properties, which may change during the execution of JVM.
+ //
+ // so we really have to create a fresh DocumentBuilder every time we need one
+ // - KK
+ DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism);
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ return dbf.newDocumentBuilder().parse(source);
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ throw new XPathExpressionException (e);
+ }
+ }
+
+ /**
+ * Get result depending on the QName type defined in XPathConstants
+ * @param resultObject the result of an evaluation
+ * @param returnType the return type
+ * @return result per the return type
+ * @throws TransformerException if the result can not be converted to
+ * the specified return type.
+ */
+ Object getResultAsType(XObject resultObject, QName returnType)
+ throws TransformerException {
+ // XPathConstants.STRING
+ if (returnType.equals(XPathConstants.STRING)) {
+ return resultObject.str();
+ }
+ // XPathConstants.NUMBER
+ if (returnType.equals(XPathConstants.NUMBER)) {
+ return resultObject.num();
+ }
+ // XPathConstants.BOOLEAN
+ if (returnType.equals(XPathConstants.BOOLEAN)) {
+ return resultObject.bool();
+ }
+ // XPathConstants.NODESET ---ORdered, UNOrdered???
+ if (returnType.equals(XPathConstants.NODESET)) {
+ return resultObject.nodelist();
+ }
+ // XPathConstants.NODE
+ if (returnType.equals(XPathConstants.NODE)) {
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ return ni.nextNode();
+ }
+ // If isSupported check is already done then the execution path
+ // shouldn't come here. Being defensive
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { returnType.toString()});
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Construct an XPathExpressionResult object based on the result of the
+ * evaluation and cast to the specified class type.
+ * @param <T> The class type
+ * @param resultObject the result of an evaluation
+ * @param type The class type expected to be returned by the XPath expression.
+ * @return an instance of the specified type or null if the XObject returned
+ * an UNKNOWN object type.
+ * @throws TransformerException if there is an error converting the result
+ * to the specified type. It's unlikely to happen. This is mostly needed
+ * by the internal XPath engine.
+ */
+ <T> T getXPathResult(XObject resultObject, Class<T> type)
+ throws TransformerException {
+ int resultType = resultObject.getType();
+
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN :
+ return type.cast(new XPathResultImpl<>(resultObject, Boolean.class));
+ case XObject.CLASS_NUMBER :
+ return type.cast(new XPathResultImpl<>(resultObject, Double.class));
+ case XObject.CLASS_STRING :
+ return type.cast(new XPathResultImpl<>(resultObject, String.class));
+ case XObject.CLASS_NODESET :
+ return type.cast(new XPathResultImpl<>(resultObject, XPathNodes.class));
+ case XObject.CLASS_RTREEFRAG : //NODE
+ return type.cast(new XPathResultImpl<>(resultObject, Node.class));
+ }
+
+ return null;
+ }
+
+ /**
+ * Check whether or not the specified type is supported
+ * @param <T> The class type
+ * @param type The type to be checked
+ * @throws IllegalArgumentException if the type is not supported
+ */
+ <T> void isSupportedClassType(Class<T> type) {
+ requireNonNull(type, "The class type");
+ if (type.isAssignableFrom(Boolean.class) ||
+ type.isAssignableFrom(Double.class) ||
+ type.isAssignableFrom(Integer.class) ||
+ type.isAssignableFrom(Long.class) ||
+ type.isAssignableFrom(String.class) ||
+ type.isAssignableFrom(XPathNodes.class) ||
+ type.isAssignableFrom(Node.class) ||
+ type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return;
+ }
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { type.toString() });
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Check if the requested returnType is supported.
+ * @param returnType the return type
+ * @throws IllegalArgumentException if the return type is not supported
+ */
+ void isSupported(QName returnType) {
+ requireNonNull(returnType, "returnType");
+ if (returnType.equals(XPathConstants.STRING) ||
+ returnType.equals(XPathConstants.NUMBER) ||
+ returnType.equals(XPathConstants.BOOLEAN) ||
+ returnType.equals(XPathConstants.NODE) ||
+ returnType.equals(XPathConstants.NODESET)) {
+ return;
+ }
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE,
+ new Object[] { returnType.toString() });
+ throw new IllegalArgumentException (fmsg);
+ }
+
+ /**
+ * Checks that the specified parameter is not {@code null}.
+ *
+ * @param <T> the type of the reference
+ * @param param the parameter to check for nullity
+ * @param paramName the parameter name
+ * @throws NullPointerException if {@code param} is {@code null}
+ */
+ <T> void requireNonNull(T param, String paramName) {
+ if (param == null) {
+ String fmsg = XSLMessages.createXPATHMessage(
+ XPATHErrorResources.ER_ARG_CANNOT_BE_NULL,
+ new Object[] {paramName});
+ throw new NullPointerException (fmsg);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import java.util.Iterator;
+import javax.xml.xpath.XPathException;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * This class implements XPathNodes that represents a set of nodes selected by
+ * evaluating an expression.
+ */
+public class XPathNodesImpl implements XPathNodes {
+ Class<Node> elementType;
+ NodeList nodeList = null;
+
+ public XPathNodesImpl(NodeList nodeList, Class<Node> elementType) {
+ this.nodeList = nodeList;
+ this.elementType = elementType;
+ }
+
+ @Override
+ public Iterator<Node> iterator() {
+ return new NodeSetIterator<>(elementType);
+ }
+
+ class NodeSetIterator<E> implements Iterator<E> {
+ int currentIndex;
+ Class<E> elementType;
+ NodeSetIterator(Class<E> elementType) {
+ this.elementType = elementType;
+ }
+ public boolean hasNext() {
+ if (nodeList != null) {
+ return currentIndex < nodeList.getLength();
+ }
+
+ return false;
+ }
+
+ public E next() {
+ if (nodeList != null && nodeList.getLength() > 0) {
+ return elementType.cast(nodeList.item(currentIndex++));
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public int size() {
+ if (nodeList != null) {
+ return nodeList.getLength();
+ }
+ return 0;
+ }
+
+ @Override
+ public Node get(int index) throws XPathException {
+ if (index <0 || index >= size()) {
+ throw new IndexOutOfBoundsException("Index " + index + " is out of bounds");
+ }
+ if (nodeList != null) {
+ return nodeList.item(index);
+ }
+ return null;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.org.apache.xpath.internal.jaxp;
+
+import com.sun.org.apache.xpath.internal.objects.XObject;
+import java.util.Objects;
+import javax.xml.transform.TransformerException;
+import javax.xml.xpath.XPathNodes;
+import javax.xml.xpath.XPathEvaluationResult;
+import javax.xml.xpath.XPathEvaluationResult.XPathResultType;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+
+
+/**
+ * This is the implementation of XPathEvaluationResult that represents the
+ * result of the evaluation of an XPath expression within the context of a
+ * particular node.
+ */
+class XPathResultImpl<T> implements XPathEvaluationResult<T> {
+
+ XObject resultObject;
+ int resultType;
+ Class<T> type;
+ XPathResultType mapToType;
+ NodeList nodeList = null;
+ int currentIndex;
+ Node currentNode;
+
+ boolean boolValue = false;
+ Node node = null;
+ double numValue;
+ String strValue;
+
+ /**
+ * Construct an XPathEvaluationResult object.
+ *
+ * @param resultObject internal XPath result object
+ * @param type class type
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ public XPathResultImpl(XObject resultObject, Class<T> type)
+ throws TransformerException {
+ this.resultObject = resultObject;
+ resultType = resultObject.getType();
+ this.type = type;
+ getResult(resultObject);
+ }
+
+ /**
+ * Return the result type as an enum specified by {@code XPathResultType}
+ * @return the result type
+ */
+ @Override
+ public XPathResultType type() {
+ return mapToType;
+ }
+
+ /**
+ * Returns the value of the result as the type <T> specified for the class.
+ *
+ * @return The value of the result.
+ */
+ @Override
+ public T value() {
+ Objects.requireNonNull(type);
+ try {
+ return getValue(resultObject, type);
+ } catch (TransformerException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /**
+ * Read the XObject and set values in accordance with the result type
+ * @param resultObject internal XPath result object
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ private void getResult(XObject resultObject) throws TransformerException {
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN:
+ boolValue = resultObject.bool();
+ mapToType = XPathResultType.BOOLEAN;
+ break;
+ case XObject.CLASS_NUMBER:
+ numValue = resultObject.num();
+ mapToType = XPathResultType.NUMBER;
+ break;
+ case XObject.CLASS_STRING:
+ strValue = resultObject.str();
+ mapToType = XPathResultType.STRING;
+ break;
+ case XObject.CLASS_NODESET:
+ mapToType = XPathResultType.NODESET;
+ nodeList = resultObject.nodelist();
+ break;
+ case XObject.CLASS_RTREEFRAG: //NODE
+ mapToType = XPathResultType.NODE;
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ node = ni.nextNode();
+ break;
+ }
+ }
+
+ /**
+ * Read the internal result object and return the value in accordance with
+ * the type specified.
+ *
+ * @param <T> The expected class type.
+ * @param resultObject internal XPath result object
+ * @param type the class type
+ * @return The value of the result, null in case of unexpected type.
+ * @throws TransformerException if there is an error reading the XPath
+ * result.
+ */
+ static <T> T getValue(XObject resultObject, Class<T> type) throws TransformerException {
+ Objects.requireNonNull(type);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return type.cast(new XPathResultImpl<T>(resultObject, type));
+ }
+ int resultType = classToInternalType(type);
+ switch (resultType) {
+ case XObject.CLASS_BOOLEAN:
+ return type.cast(resultObject.bool());
+ case XObject.CLASS_NUMBER:
+ if (Double.class.isAssignableFrom(type)) {
+ return type.cast(resultObject.num());
+ } else if (Integer.class.isAssignableFrom(type)) {
+ return type.cast((int)resultObject.num());
+ } else if (Long.class.isAssignableFrom(type)) {
+ return type.cast((long)resultObject.num());
+ }
+ /*
+ This is to suppress warnings. By the current specification,
+ among numeric types, only Double, Integer and Long are supported.
+ */
+ break;
+ case XObject.CLASS_STRING:
+ return type.cast(resultObject.str());
+ case XObject.CLASS_NODESET:
+ XPathNodes nodeSet = new XPathNodesImpl(resultObject.nodelist(),
+ Node.class);
+ return type.cast(nodeSet);
+ case XObject.CLASS_RTREEFRAG: //NODE
+ NodeIterator ni = resultObject.nodeset();
+ //Return the first node, or null
+ return type.cast(ni.nextNode());
+ }
+
+ return null;
+ }
+
+ /**
+ * Map the specified class type to the internal result type
+ *
+ * @param <T> The expected class type.
+ * @param type the class type
+ * @return the internal XObject type.
+ */
+ static <T> int classToInternalType(Class<T> type) {
+ if (type.isAssignableFrom(Boolean.class)) {
+ return XObject.CLASS_BOOLEAN;
+ } else if (Number.class.isAssignableFrom(type)) {
+ return XObject.CLASS_NUMBER;
+ } else if (type.isAssignableFrom(String.class)) {
+ return XObject.CLASS_STRING;
+ } else if (type.isAssignableFrom(XPathNodes.class)) {
+ return XObject.CLASS_NODESET;
+ } else if (type.isAssignableFrom(Node.class)) {
+ return XObject.CLASS_RTREEFRAG;
+ }
+ return XObject.CLASS_NULL;
+ }
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,12 +25,12 @@
package javax.xml.xpath;
-import org.xml.sax.InputSource;
+import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
-import javax.xml.namespace.NamespaceContext;
+import org.xml.sax.InputSource;
/**
- * <p><code>XPath</code> provides access to the XPath evaluation environment and expressions.</p>
+ * {@code XPath} provides access to the XPath evaluation environment and expressions.
*
* <a name="XPath-evaluation"/>
* <table border="1" cellpadding="2">
@@ -39,7 +39,6 @@
* <th colspan="2">Evaluation of XPath Expressions.</th>
* </tr>
* </thead>
- * <tbody>
* <tr>
* <td>context</td>
* <td>
@@ -55,8 +54,8 @@
* If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver}
* set with {@link #setXPathVariableResolver(XPathVariableResolver resolver)}.
* An {@link XPathExpressionException} is raised if the variable resolver is undefined or
- * the resolver returns <code>null</code> for the variable.
- * The value of a variable must be immutable through the course of any single evaluation.</p>
+ * the resolver returns {@code null} for the variable.
+ * The value of a variable must be immutable through the course of any single evaluation.
* </td>
* </tr>
* <tr>
@@ -65,7 +64,7 @@
* If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver}
* set with {@link #setXPathFunctionResolver(XPathFunctionResolver resolver)}.
* An {@link XPathExpressionException} is raised if the function resolver is undefined or
- * the function resolver returns <code>null</code> for the function.</p>
+ * the function resolver returns {@code null} for the function.
* </td>
* </tr>
* <tr>
@@ -80,7 +79,7 @@
* <td>
* This result of evaluating an expression is converted to an instance of the desired return type.
* Valid return types are defined in {@link XPathConstants}.
- * Conversion to the return type follows XPath conversion rules.</p>
+ * Conversion to the return type follows XPath conversion rules.
* </td>
* </tr>
* </table>
@@ -88,9 +87,9 @@
* <p>An XPath object is not thread-safe and not reentrant.
* In other words, it is the application's responsibility to make
* sure that one {@link XPath} object is not used from
- * more than one thread at any given time, and while the <code>evaluate</code>
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the <code>evaluate</code> method.
+ * the {@code evaluate} method.
* <p>
*
* @author <a href="Norman.Walsh@Sun.com">Norman Walsh</a>
@@ -100,191 +99,189 @@
*/
public interface XPath {
- /**
- * <p>Reset this <code>XPath</code> to its original configuration.</p>
- *
- * <p><code>XPath</code> is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s
- * thus saving resources associated with the creation of new <code>XPath</code>s.</p>
- *
- * <p>The reset <code>XPath</code> is not guaranteed to have the same {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>, <code>XPathVariableResolver</code>
- * and <code>NamespaceContext</code>.</p>
- */
- public void reset();
/**
- * <p>Establish a variable resolver.</p>
+ * Reset this {@code XPath} to its original configuration.
+ *
+ * <p>{@code XPath} is reset to the same state as when it was created with
+ * {@link XPathFactory#newXPath()}.
+ * {@code reset()} is designed to allow the reuse of existing {@code XPath}s
+ * thus saving resources associated with the creation of new {@code XPath}s.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
+ * <p>The reset {@code XPath} is not guaranteed to have the same
+ * {@link XPathFunctionResolver}, {@link XPathVariableResolver}
+ * or {@link NamespaceContext} {@code Object}s, e.g. {@link Object#equals(Object obj)}.
+ * It is guaranteed to have a functionally equal {@code XPathFunctionResolver},
+ * {@code XPathVariableResolver} and {@code NamespaceContext}.
+ */
+ public void reset();
+
+ /**
+ * Establish a variable resolver.
+ *
+ * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver Variable resolver.
*
- * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathVariableResolver(XPathVariableResolver resolver);
/**
- * <p>Return the current variable resolver.</p>
+ * Return the current variable resolver.
*
- * <p><code>null</code> is returned in no variable resolver is in effect.</p>
+ * <p>{@code null} is returned in no variable resolver is in effect.
*
* @return Current variable resolver.
*/
public XPathVariableResolver getXPathVariableResolver();
/**
- * <p>Establish a function resolver.</p>
+ * Establish a function resolver.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p>
+ * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver XPath function resolver.
*
- * @throws NullPointerException If <code>resolver</code> is <code>null</code>.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathFunctionResolver(XPathFunctionResolver resolver);
/**
- * <p>Return the current function resolver.</p>
- *
- * <p><code>null</code> is returned in no function resolver is in effect.</p>
+ * Return the current function resolver.
+ * <p>
+ * {@code null} is returned in no function resolver is in effect.
*
* @return Current function resolver.
*/
public XPathFunctionResolver getXPathFunctionResolver();
/**
- * <p>Establish a namespace context.</p>
+ * Establish a namespace context.
*
- * <p>A <code>NullPointerException</code> is thrown if <code>nsContext</code> is <code>null</code>.</p>
+ * <p>A {@code NullPointerException} is thrown if {@code nsContext} is {@code null}.
*
* @param nsContext Namespace context to use.
*
- * @throws NullPointerException If <code>nsContext</code> is <code>null</code>.
+ * @throws NullPointerException If {@code nsContext} is {@code null}.
*/
public void setNamespaceContext(NamespaceContext nsContext);
/**
- * <p>Return the current namespace context.</p>
+ * Return the current namespace context.
*
- * <p><code>null</code> is returned in no namespace context is in effect.</p>
+ * <p>{@code null} is returned in no namespace context is in effect.
*
* @return Current Namespace context.
*/
public NamespaceContext getNamespaceContext();
/**
- * <p>Compile an XPath expression for later evaluation.</p>
+ * Compile an XPath expression for later evaluation.
*
- * <p>If <code>expression</code> contains any {@link XPathFunction}s,
+ * <p>If {@code expression} contains any {@link XPathFunction}s,
* they must be available via the {@link XPathFunctionResolver}.
* An {@link XPathExpressionException} will be thrown if the
- * <code>XPathFunction</code>
- * cannot be resovled with the <code>XPathFunctionResolver</code>.</p>
+ * {@code XPathFunction}
+ * cannot be resovled with the {@code XPathFunctionResolver}.
*
- * <p>If <code>expression</code> contains any variables, the
+ * <p>If {@code expression} contains any variables, the
* {@link XPathVariableResolver} in effect
- * <strong>at compile time</strong> will be used to resolve them.</p>
- *
- * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p>
+ * <strong>at compile time</strong> will be used to resolve them.
*
* @param expression The XPath expression.
*
* @return Compiled XPath expression.
- * @throws XPathExpressionException If <code>expression</code> cannot be compiled.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
+ * @throws XPathExpressionException If {@code expression} cannot be compiled.
+ * @throws NullPointerException If {@code expression} is {@code null}.
*/
public XPathExpression compile(String expression)
throws XPathExpressionException;
/**
- * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p>
+ * Evaluate an {@code XPath} expression in the specified context and
+ * return the result as the specified type.
*
- * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and <code>QName</code> resolution and return type conversion.</p>
+ * <p>
+ * See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a>
+ * for context item evaluation, variable, function and {@code QName} resolution
+ * and return type conversion.
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} (
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param returnType The result type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating an XPath expression as an {@code Object} of {@code returnType}.
+ *
+ * @throws XPathExpressionException If {@code expression} cannot be evaluated.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants} (
* {@link XPathConstants#NUMBER NUMBER},
* {@link XPathConstants#STRING STRING},
* {@link XPathConstants#BOOLEAN BOOLEAN},
* {@link XPathConstants#NODE NODE} or
- * {@link XPathConstants#NODESET NODESET})
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a
- * <code>NullPointerException</code> is thrown.</p>
- *
- * @param expression The XPath expression.
- * @param item The starting context (a node, for example).
- * @param returnType The desired return type.
- *
- * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>.
- *
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>.
+ * {@link XPathConstants#NODESET NODESET}).
+ * @throws NullPointerException If {@code expression or returnType} is {@code null}.
*/
public Object evaluate(String expression, Object item, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p>
+ * Evaluate an XPath expression in the specified context and return the result as a {@code String}.
*
- * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of
- * {@link XPathConstants#STRING}.</p>
+ * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a {@code returnType} of
+ * {@link XPathConstants#STRING}.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
+ * variable, function and QName resolution and return type conversion.
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
* @param expression The XPath expression.
- * @param item The starting context (a node, for example).
+ * @param item The context the XPath expression will be evaluated in.
*
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
+ * @return The result of evaluating an XPath expression as a {@code String}.
*
- * @throws XPathExpressionException If <code>expression</code> cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> is <code>null</code>.
+ * @throws XPathExpressionException If {@code expression} cannot be evaluated.
+ * @throws NullPointerException If {@code expression} is {@code null}.
*/
public String evaluate(String expression, Object item)
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as the specified type.</p>
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as the specified type.
*
* <p>This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p>
+ * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
- *
- * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * variable, function and QName resolution and return type conversion.
*
* @param expression The XPath expression.
* @param source The input source of the document to evaluate over.
* @param returnType The desired return type.
*
- * @return The <code>Object</code> that encapsulates the result of evaluating the expression.
+ * @return The {@code Object} that encapsulates the result of evaluating the expression.
*
* @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code>
- * is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code expression, source or returnType} is {@code null}.
*/
public Object evaluate(
String expression,
@@ -293,27 +290,209 @@
throws XPathExpressionException;
/**
- * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code>
- * and return the result as a <code>String</code>.</p>
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as a {@code String}.
*
* <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * <code>returnType</code> of {@link XPathConstants#STRING}.</p>
+ * {@code returnType} of {@link XPathConstants#STRING}.
*
* <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
- * variable, function and QName resolution and return type conversion.</p>
- *
- * <p>If <code>expression</code> or <code>source</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * variable, function and QName resolution and return type conversion.
*
* @param expression The XPath expression.
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The <code>String</code> that is the result of evaluating the expression and
- * converting the result to a <code>String</code>.
+ * @return The {@code String} that is the result of evaluating the expression and
+ * converting the result to a {@code String}.
*
* @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>.
+ * @throws NullPointerException If {@code expression or source} is {@code null}.
*/
public String evaluate(String expression, InputSource source)
throws XPathExpressionException;
+
+ /**
+ * Evaluate an XPath expression in the specified context and return
+ * the result with the type specified through the {@code class type}
+ *
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (T)evaluate(expression, item,
+ * XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType},
+ * or XPathEvaluationResult is specified as the type but an implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code expression or type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(String expression, Object item, Class<T> type)
+ throws XPathExpressionException {
+ return type.cast(evaluate(expression, item,
+ XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate an XPath expression in the specified context. This is equivalent to
+ * calling {@link #evaluateExpression(String expression, Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param expression The XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code expression} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(String expression, Object item)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(expression, item, XPathEvaluationResult.class);
+ }
+
+ /**
+ * Evaluate an XPath expression in the context of the specified {@code source}
+ * and return the result as specified.
+ * <p>
+ * This method builds a data model for the {@link InputSource} and calls
+ * {@link #evaluateExpression(String expression, Object item, Class type)}
+ * on the resulting document object. The data model is usually
+ * {@link org.w3c.dom.Document}
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ (T)evaluate(expression, source,
+ XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param expression The XPath expression.
+ * @param source The input source of the document to evaluate over.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code expression, source or type}is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(String expression, InputSource source, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(expression, source,
+ XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate an XPath expression in the specified context. This is equivalent to
+ * calling {@link #evaluateExpression(String expression, Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(expression, item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(expression, source, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param expression The XPath expression.
+ * @param source The input source of the document to evaluate over.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code expression or source} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(expression, source, XPathEvaluationResult.class);
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. 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 javax.xml.xpath;
+
+import java.util.Objects;
+import javax.xml.namespace.QName;
+import org.w3c.dom.Node;
+/**
+ * The {@code XPathEvaluationResult} interface represents the result of the
+ * evaluation of an XPath expression within the context of a particular node.
+ * The evaluation of an XPath expression can result in various result types as
+ * defined in XML Path Language (XPath) Version 1.0.
+ * <p>
+ *
+ * @param <T> the object type returned by the XPath evaluation.
+ * @see <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version
+ * 1.0</a>
+ *
+ * @since 1.9
+ */
+public interface XPathEvaluationResult<T> {
+
+ /**
+ * XPathResultType represents possible return types of an XPath evaluation.
+ * Provided as an enum type, it allows the use of switch statement. At the
+ * same time, a mapping is provided between the original QName types in
+ * {@link XPathConstants} and class types used in the generic methods.
+ */
+ public static enum XPathResultType {
+ /**
+ * Any type that represents any of the 5 other types listed below.
+ * Maps to {@link XPathEvaluationResult}.
+ */
+ ANY(new QName("http://www.w3.org/1999/XSL/Transform", "any"), XPathEvaluationResult.class),
+ /**
+ * The XPath 1.0 boolean data type. Maps to Java {@link Boolean}.
+ */
+ BOOLEAN(XPathConstants.BOOLEAN, Boolean.class),
+ /**
+ * The XPath 1.0 Number data type. Maps to Java {@link Number}. Of the
+ * subtypes of Number, only Double, Integer and Long are required.
+ */
+ NUMBER(XPathConstants.NUMBER, Number.class),
+ /**
+ * The XPath 1.0 String data type. Maps to Java {@link String}.
+ */
+ STRING(XPathConstants.STRING, String.class),
+ /**
+ * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.NodeList}.
+ */
+ NODESET(XPathConstants.NODESET, XPathNodes.class),
+ /**
+ * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.Node}.
+ */
+ NODE(XPathConstants.NODE, Node.class);
+
+ final QName qnameType;
+ final Class<?> clsType;
+ XPathResultType(QName qnameType, Class<?> clsType) {
+ this.qnameType = qnameType;
+ this.clsType = clsType;
+ }
+
+ /**
+ * Compares this type to the specified class type.
+ * @param clsType class type
+ * @return true if the argument is not null and is a class type that
+ * matches that this type represents, false otherwise.
+ */
+ private boolean equalsClassType(Class<?> clsType) {
+ Objects.nonNull(clsType);
+ if (clsType.isAssignableFrom(this.clsType)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the QName type as specified in {@link XPathConstants} that
+ * corresponds to the specified class type.
+ * @param clsType a class type that the enum type supports
+ * @return the QName type that matches with the specified class type,
+ * null if there is no match
+ */
+ static public QName getQNameType(Class<?> clsType) {
+ for (XPathResultType type : XPathResultType.values()) {
+ if (type.equalsClassType(clsType)) {
+ return type.qnameType;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Return the result type as an enum specified by {@code XPathResultType}
+ * @return the result type
+ */
+ public XPathResultType type();
+
+ /**
+ * Returns the value of the result as the type <T> specified for the class.
+ *
+ * @return The value of the result.
+ */
+ public T value();
+
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,11 @@
package javax.xml.xpath;
+import javax.xml.namespace.QName;
import org.xml.sax.InputSource;
-import javax.xml.namespace.QName;
/**
- * <p><code>XPathExpression</code> provides access to compiled XPath expressions.</p>
+ * <p>{@code XPathExpression} provides access to compiled XPath expressions.</p>
*
* <a name="XPathExpression-evaluation"/>
* <table border="1" cellpadding="2">
@@ -53,7 +53,7 @@
* <td>
* If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver}.
* An {@link XPathExpressionException} is raised if the variable resolver is undefined or
- * the resolver returns <code>null</code> for the variable.
+ * the resolver returns {@code null} for the variable.
* The value of a variable must be immutable through the course of any single evaluation.</p>
* </td>
* </tr>
@@ -62,7 +62,7 @@
* <td>
* If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver}.
* An {@link XPathExpressionException} is raised if the function resolver is undefined or
- * the function resolver returns <code>null</code> for the function.</p>
+ * the function resolver returns {@code null} for the function.</p>
* </td>
* </tr>
* <tr>
@@ -84,9 +84,9 @@
* <p>An XPath expression is not thread-safe and not reentrant.
* In other words, it is the application's responsibility to make
* sure that one {@link XPathExpression} object is not used from
- * more than one thread at any given time, and while the <code>evaluate</code>
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the <code>evaluate</code> method.
+ * the {@code evaluate} method.
* <p>
*
* @author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a>
@@ -96,50 +96,56 @@
*/
public interface XPathExpression {
+
/**
* <p>Evaluate the compiled XPath expression in the specified context and return the result as the specified type.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
- * If <code>returnType</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
- * @param item The starting context (a node, for example).
- * @param returnType The desired return type.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param returnType The result type expected to be returned by the XPath expression.
*
- * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to
- * <code>returnType</code>.
+ * @return The {@code Object} that is the result of evaluating the expression and converting the result to
+ * {@code returnType}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>returnType</code> is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code returnType} is {@code null}.
*/
public Object evaluate(Object item, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the specified context and return the result as a <code>String</code>.</p>
+ * <p>Evaluate the compiled XPath expression in the specified context and return the result as a {@code String}.</p>
*
- * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a <code>returnType</code> of
+ * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If a <code>null</code> value is provided for
- * <code>item</code>, an empty document will be used for the
- * context.
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
*
- * @param item The starting context (a node, for example).
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
*
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating an XPath expression as a {@code String}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
*/
@@ -147,7 +153,7 @@
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as the
+ * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as the
* specified type.</p>
*
* <p>This method builds a data model for the {@link InputSource} and calls
@@ -156,45 +162,225 @@
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants},
- * then an <code>IllegalArgumentException</code> is thrown.</p>
+ * <p>If {@code returnType} is not one of the types defined in {@link XPathConstants},
+ * then an {@code IllegalArgumentException} is thrown.</p>
*
- * <p>If <code>source</code> or <code>returnType</code> is <code>null</code>,
- * then a <code>NullPointerException</code> is thrown.</p>
+ * <p>If {@code source} or {@code returnType} is {@code null},
+ * then a {@code NullPointerException} is thrown.</p>
*
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
* @param returnType The desired return type.
*
- * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to
- * <code>returnType</code>.
+ * @return The {@code Object} that is the result of evaluating the expression and converting the result to
+ * {@code returnType}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If <code>source</code> or <code>returnType</code> is <code>null</code>.
+ * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}.
+ * @throws NullPointerException If {@code source or returnType} is {@code null}.
*/
public Object evaluate(InputSource source, QName returnType)
throws XPathExpressionException;
/**
- * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a
- * <code>String</code>.</p>
+ * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as a
+ * {@code String}.</p>
*
- * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of
+ * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.</p>
*
* <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation,
* variable, function and QName resolution and return type conversion.</p>
*
- * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p>
+ * <p>If {@code source} is {@code null}, then a {@code NullPointerException} is thrown.</p>
*
- * @param source The <code>InputSource</code> of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a
- * <code>String</code>.
+ * @return The {@code String} that is the result of evaluating the expression and converting the result to a
+ * {@code String}.
*
* @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws NullPointerException If <code>source</code> is <code>null</code>.
+ * @throws NullPointerException If {@code source} is {@code null}.
*/
public String evaluate(InputSource source)
throws XPathExpressionException;
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context, and return
+ * the result with the type specified through the {@code class type}.
+ *
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (T)evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param item The context the XPath expression will be evaluated in.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available.
+ * @throws NullPointerException If {@code type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(Object item, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context. This is
+ * equivalent to calling {@link #evaluateExpression(Object item, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(item, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ * The parameter {@code item} represents the context the XPath expression
+ * will be operated on. The type of the context is implementation-dependent.
+ * If the value is {@code null}, the operation must have no dependency on
+ * the context, otherwise an XPathExpressionException will be thrown.
+ *
+ * @implNote
+ * The type of the context is usually {@link org.w3c.dom.Node}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * evaluateExpression(item, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param item The context the XPath expression will be evaluated in.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(Object item)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(item, XPathEvaluationResult.class);
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context,
+ * and return the result with the type specified through the {@code class type}
+ * <p>
+ * This method builds a data model for the {@link InputSource} and calls
+ * {@link #evaluateExpression(Object item, Class type)} on the resulting
+ * document object.
+ * <P>
+ * By default, the JDK's data model is {@link org.w3c.dom.Document}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ (T)evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type));
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying
+ * XPathEvaluationResult as the type will result in IllegalArgumentException.
+ * Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override
+ * this method.
+ *
+ * @param <T> The class type that will be returned by the XPath expression.
+ * @param source The {@code InputSource} of the document to evaluate over.
+ * @param type The class type expected to be returned by the XPath expression.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If {@code type} is not of the types
+ * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType
+ * XPathResultType}, or XPathEvaluationResult is specified as the type but an
+ * implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type
+ * is not available.
+ * @throws NullPointerException If {@code source or type} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default <T>T evaluateExpression(InputSource source, Class<T> type)
+ throws XPathExpressionException
+ {
+ return type.cast(evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type)));
+ }
+
+ /**
+ * Evaluate the compiled XPath expression in the specified context. This is
+ * equivalent to calling {@link #evaluateExpression(InputSource source, Class type)}
+ * with type {@link XPathEvaluationResult}:
+ * <pre> {@code
+ * evaluateExpression(source, XPathEvaluationResult.class);
+ * }</pre>
+ * <p>
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ * <pre> {@code
+ * (XPathEvaluationResult)evaluateExpression(source, XPathEvaluationResult.class);
+ * }</pre>
+ *
+ * Since the {@code evaluate} method does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY}
+ * type, the default implementation of this method will always throw an
+ * IllegalArgumentException. Any implementation supporting the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore
+ * override this method.
+ *
+ * @param source The {@code InputSource} of the document to evaluate over.
+ *
+ * @return The result of evaluating the expression.
+ *
+ * @throws XPathExpressionException If the expression cannot be evaluated.
+ * @throws IllegalArgumentException If the implementation of this method
+ * does not support the
+ * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type.
+ * @throws NullPointerException If {@code source} is {@code null}.
+ *
+ * @since 1.9
+ */
+ default XPathEvaluationResult<?> evaluateExpression(InputSource source)
+ throws XPathExpressionException
+ {
+ return evaluateExpression(source, XPathEvaluationResult.class);
+ }
}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Mon Feb 09 09:52:48 2015 -0800
@@ -117,7 +117,7 @@
* and returns it if it is successfully created.
* </li>
* <li>
- * ${java.home}/conf/jaxp.properties is read and the value associated with the key being the system property above is looked for.
+ * ${java.home}/lib/jaxp.properties is read and the value associated with the key being the system property above is looked for.
* If present, the value is processed just like above.
* </li>
* <li>
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Mon Feb 09 09:52:48 2015 -0800
@@ -176,9 +176,9 @@
String javah = ss.getSystemProperty( "java.home" );
String configFile = javah + File.separator +
- "conf" + File.separator + "jaxp.properties";
+ "lib" + File.separator + "jaxp.properties";
- // try to read from $java.home/conf/jaxp.properties
+ // try to read from $java.home/lib/jaxp.properties
try {
if(firstTime){
synchronized(cacheProps){
@@ -193,7 +193,7 @@
}
}
final String factoryClassName = cacheProps.getProperty(propertyName);
- debugPrintln("found " + factoryClassName + " in $java.home/conf/jaxp.properties");
+ debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
if (factoryClassName != null) {
xpathFactory = createInstance(factoryClassName, true);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.xpath;
+
+import java.util.Iterator;
+import org.w3c.dom.Node;
+
+/**
+ * XPathNodes represents a set of nodes selected by a location path as specified
+ * in <a href="http://www.w3.org/TR/xpath/#node-sets">XML Path Language (XPath)
+ * Version 1.0, 3.3 Node-sets</a>.
+ *
+ * @since 1.9
+ */
+public interface XPathNodes extends Iterable<Node> {
+
+ /**
+ * Returns an iterator of the Nodes.
+ *
+ * @return an Iterator.
+ */
+ @Override
+ public abstract Iterator<Node> iterator();
+
+ /**
+ * Returns the number of items in the result
+ *
+ * @return The number of items in the result
+ */
+ public abstract int size();
+
+ /**
+ * Returns a Node at the specified position
+ *
+ * @param index Index of the element to return.
+ * @return The Node at the specified position.
+ * @throws javax.xml.xpath.XPathException If the index is out of range
+ * (index < 0 || index >= size())
+ */
+ public abstract Node get(int index)
+ throws XPathException;
+}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Mon Feb 09 09:52:48 2015 -0800
@@ -1,6 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
+<html>
+<head>
<!--
-Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
@@ -23,35 +25,35 @@
or visit www.oracle.com if you need additional information or have any
questions.
-->
+</head>
+<body bgcolor="white">
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title>javax.xml.xpath</title>
-<meta name="@author" content="mailto:Ben@galbraiths.org" />
-<meta name="@author" content="mailto:Norman.Walsh@Sun.com" />
-<meta name="@author" content="mailto:Jeff.Suttor@Sun.com" />
-<meta name="@see" content="http://www.w3.org/TR/xpath" />
-<meta name="@since" content="1.5" />
-</head>
-
-<body>
-
-<p>This package provides an <em>object-model neutral</em> API for the
+This package provides an <em>object-model neutral</em> API for the
evaluation of XPath expressions and access to the evaluation
environment.
-</p>
-<p>The following XML standards apply:</p>
-
-<ul>
-<li><a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li>
-</ul>
+<p>
+The XPath API supports <a href="http://www.w3.org/TR/xpath">
+ XML Path Language (XPath) Version 1.0</a>
<hr />
-<h2>XPath Overview</h2>
+<ul>
+ <li><a href='#XPath.Overview'>1. XPath Overview</a></li>
+ <li><a href='#XPath.Expressions'>2. XPath Expressions</a></li>
+ <li><a href='#XPath.Datatypes'>3. XPath Data Types</a>
+ <ul>
+ <li><a href='#XPath.Datatypes.QName'>3.1 QName Types</a>
+ <li><a href='#XPath.Datatypes.Class'>3.2 Class Types</a>
+ <li><a href='#XPath.Datatypes.Enum'>3.3 Enum Types</a>
+ </ul>
+ </li>
+ <li><a href='#XPath.Context'>4. XPath Context</a></li>
+ <li><a href='#XPath.Use'>5. Using the XPath API</a></li>
+</ul>
+<p>
+<a name="XPath.Overview"></a>
+<h3>1. XPath Overview</h3>
<p>The XPath language provides a simple, concise syntax for selecting
nodes from an XML document. XPath also provides rules for converting a
@@ -67,7 +69,8 @@
replace many lines of DOM API code.
</p>
-<h3>XPath Expressions</h3>
+<a name="XPath.Expressions"></a>
+<h3>2. XPath Expressions</h3>
<p>An XPath <em>expression</em> is composed of a <em>location
path</em> and one or more optional <em>predicates</em>. Expressions
@@ -76,18 +79,22 @@
<p>The following is an example of a simple XPath expression:</p>
+<blockquote>
<pre>
/foo/bar
</pre>
+</blockquote>
<p>This example would select the <code><bar></code> element in
an XML document such as the following:</p>
+<blockquote>
<pre>
<foo>
-<bar/>
+ <bar/>
</foo>
</pre>
+</blockquote>
<p>The expression <code>/foo/bar</code> is an example of a location
path. While XPath location paths resemble Unix-style file system
@@ -96,30 +103,36 @@
<code><bar></code> elements in the following document would be
selected by the <code>/foo/bar</code> expression:</p>
+<blockquote>
<pre>
<foo>
-<bar/>
-<bar/>
-<bar/>
+ <bar/>
+ <bar/>
+ <bar/>
</foo>
</pre>
+</blockquote>
<p>A special location path operator, <code>//</code>, selects nodes at
any depth in an XML document. The following example selects all
<code><bar></code> elements regardless of their location in a
document:</p>
+<blockquote>
<pre>
//bar
</pre>
+</blockquote>
<p>A wildcard operator, *, causes all element nodes to be selected.
The following example selects all children elements of a
-<code><foo></code> element:</p>
+<code><foo></code> element:
+<blockquote>
<pre>
/foo/*
</pre>
+</blockquote>
<p>In addition to element nodes, XPath location paths may also address
attribute nodes, text nodes, comment nodes, and processing instruction
@@ -166,35 +179,27 @@
<code><foo></code> elements that contain an <code>include</code>
attribute with the value of <code>true</code>:</p>
+<blockquote>
<pre>
//foo[@include='true']
</pre>
+</blockquote>
<p>Predicates may be appended to each other to further refine an
expression, such as:</p>
+<blockquote>
<pre>
//foo[@include='true'][@mode='bar']
</pre>
-
-<h3>Using the XPath API</h3>
-
-<p>
-The following example demonstrates using the XPath API to select one
-or more nodes from an XML document:</p>
+</blockquote>
-<pre>
-XPath xpath = XPathFactory.newInstance().newXPath();
-String expression = "/widgets/widget";
-InputSource inputSource = new InputSource("widgets.xml");
-NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
-</pre>
-
-<h3>XPath Expressions and Types</h3>
+<a name="XPath.Datatypes"></a>
+<h3>3. XPath Data Types</h3>
<p>While XPath expressions select nodes in the XML document, the XPath
API allows the selected nodes to be coalesced into one of the
-following other data types:</p>
+following data types:</p>
<ul>
<li><code>Boolean</code></li>
@@ -202,14 +207,10 @@
<li><code>String</code></li>
</ul>
-<p>The desired return type is specified by a {@link
-javax.xml.namespace.QName} parameter in method call used to evaluate
-the expression, which is either a call to
-<code>XPathExpression.evalute(...)</code> or to one of the
-<code>XPath.evaluate(...)</code> convenience methods. The allowed
-QName values are specified as constants in the {@link
-javax.xml.xpath.XPathConstants} class; they are:</p>
-
+<a name="XPath.Datatypes.QName"></a>
+<h3>3.1 QName types</h3>
+The XPath API defines the following {@link javax.xml.namespace.QName} types to
+represent return types of an XPath evaluation:
<ul>
<li>{@link javax.xml.xpath.XPathConstants#NODESET}</li>
<li>{@link javax.xml.xpath.XPathConstants#NODE}</li>
@@ -218,26 +219,71 @@
<li>{@link javax.xml.xpath.XPathConstants#NUMBER}</li>
</ul>
+<p>The return type is specified by a {@link javax.xml.namespace.QName} parameter
+in method call used to evaluate the expression, which is either a call to
+<code>XPathExpression.evalute(...)</code> or <code>XPath.evaluate(...)</code>
+methods.
+
<p>When a <code>Boolean</code> return type is requested,
<code>Boolean.TRUE</code> is returned if one or more nodes were
-selected; otherwise, <code>Boolean.FALSE</code> is returned.</p>
+selected; otherwise, <code>Boolean.FALSE</code> is returned.
<p>The <code>String</code> return type is a convenience for retrieving
the character data from a text node, attribute node, comment node, or
processing-instruction node. When used on an element node, the value
of the child text nodes is returned.
-</p>
<p>The <code>Number</code> return type attempts to coalesce the text
of a node to a <code>double</code> data type.
-</p>
+
+<a name="XPath.Datatypes.Class"></a>
+<h3>3.2 Class types</h3>
+In addition to the QName types, the XPath API supports the use of Class types
+through the <code>XPathExpression.evaluteExpression(...)</code> or
+<code>XPath.evaluateExpression(...)</code> methods.
-<h3>XPath Context</h3>
+The XPath data types are mapped to Class types as follows:
+<ul>
+<li><code>Boolean</code> -- <code>Boolean.class</code></li>
+<li><code>Number</code> -- <code>Number.class</code></li>
+<li><code>String</code> -- <code>String.class</code></li>
+<li><code>Nodeset</code> -- <code>XPathNodes.class</code></li>
+<li><code>Node</code> -- <code>Node.class</code></li>
+</ul>
+
+<p>
+Of the subtypes of Number, only Double, Integer and Long are supported.
+
+<a name="XPath.Datatypes.Enum"></a>
+<h3>3.3 Enum types</h3>
+Enum types are defined in {@link javax.xml.xpath.XPathEvaluationResult.XPathResultType}
+that provide mappings between the QName and Class types above. The result of
+evaluating an expression using the <code>XPathExpression.evaluteExpression(...)</code>
+or <code>XPath.evaluateExpression(...)</code> methods will be of one of these types.
+
+<a name="XPath.Context"></a>
+<h3>4. XPath Context</h3>
<p>XPath location paths may be relative to a particular node in the
-document, known as the <code>context</code>. Consider the following
-XML document:</p>
+document, known as the <code>context</code>. A context consists of:
+<ul>
+ <li>a node (the context node)</li>
+ <li>a pair of non-zero positive integers (the context position and the context size)</li>
+ <li>a set of variable bindings</li>
+ <li>a function library</li>
+ <li>the set of namespace declarations in scope for the expression</li>
+</ul>
+<p>
+It is an XML document tree represented as a hierarchy of nodes, a
+{@link org.w3c.dom.Node} for example, in the JDK implementation.
+
+<a name="XPath.Use"></a>
+<h3>5. Using the XPath API</h3>
+
+Consider the following XML document:
+<p>
+<blockquote>
<pre>
<widgets>
<widget>
@@ -246,36 +292,88 @@
</widget>
</widgets>
</pre>
+</blockquote>
-<p>The <code><widget></code> element can be selected with the
-following XPath API code:</p>
+<p>
+The <code><widget></code> element can be selected with the following process:
+<blockquote>
<pre>
// parse the XML as a W3C Document
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = builder.parse(new File("/widgets.xml"));
+//Get an XPath object and evaluate the expression
XPath xpath = XPathFactory.newInstance().newXPath();
String expression = "/widgets/widget";
Node widgetNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE);
+
+//or using the evaluateExpression method
+Node widgetNode = xpath.evaluateExpression(expression, document, Node.class);
</pre>
+</blockquote>
<p>With a reference to the <code><widget></code> element, a
-relative XPath expression can now written to select the
+relative XPath expression can be written to select the
<code><manufacturer></code> child element:</p>
+<blockquote>
<pre>
XPath xpath = XPathFactory.newInstance().newXPath();
<strong>String expression = "manufacturer";</strong>
Node manufacturerNode = (Node) xpath.evaluate(expression, <strong>widgetNode</strong>, XPathConstants.NODE);
+
+//or using the evaluateExpression method
+Node manufacturerNode = xpath.evaluateExpression(expression, <strong>widgetNode</strong>, Node.class);
</pre>
+</blockquote>
+
+<p>
+In the above example, the XML file is read into a DOM Document before being passed
+to the XPath API. The following code demonstrates the use of InputSource to
+leave it to the XPath implementation to process it:
+
+<blockquote>
+<pre>
+XPath xpath = XPathFactory.newInstance().newXPath();
+String expression = "/widgets/widget";
+InputSource inputSource = new InputSource("widgets.xml");
+NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET);
+
+//or using the evaluateExpression method
+XPathNodes nodes = xpath.evaluate(expression, inputSource, XPathNodes.class);
+</pre>
+</blockquote>
-<ul>
-<li>Author <a href="mailto:Ben@galbraiths.org">Ben Galbraith</a></li>
-<li>Author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a></li>
-<li>Author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a></li>
-<li>See <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li>
-<li>Since 1.5</li>
-</ul>
+<p>
+In the above cases, the type of the expected results are known. In case where
+the result type is unknown or any type, the {@link javax.xml.xpath.XPathEvaluationResult}
+may be used to determine the return type. The following code demonstrates the usage:
+<blockquote>
+<pre>
+XPathEvaluationResult<?> result = xpath.evaluateExpression(expression, document);
+switch (result.type()) {
+ case NODESET:
+ XPathNodes nodes = (XPathNodes)result.value();
+ ...
+ break;
+}
+</pre>
+</blockquote>
+
+<p>
+The XPath 1.0 Number data type is defined as a double. However, the XPath
+specification also provides functions that returns Integer type. To facilitate
+such operations, the XPath API allows Integer and Long to be used in
+{@code evaluateExpression} method such as the following code:
+<p>
+<blockquote>
+<pre>
+int count = xpath.evaluate("count(/widgets/widget)", document, Integer.class);
+</pre>
+</blockquote>
+
+@since 1.5
+
</body>
</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/DurationTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,585 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.datatype.ptests;
+
+import static javax.xml.datatype.DatatypeConstants.DAYS;
+import static javax.xml.datatype.DatatypeConstants.HOURS;
+import static javax.xml.datatype.DatatypeConstants.MINUTES;
+import static javax.xml.datatype.DatatypeConstants.MONTHS;
+import static javax.xml.datatype.DatatypeConstants.SECONDS;
+import static javax.xml.datatype.DatatypeConstants.YEARS;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Calendar;
+import java.util.function.Function;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.namespace.QName;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @summary Class containing the test cases for Duration.
+ */
+public class DurationTest extends JAXPBaseTest {
+
+ private DatatypeFactory datatypeFactory;
+
+ /*
+ * Setup.
+ */
+ @BeforeClass
+ public void setup() throws DatatypeConfigurationException {
+ datatypeFactory = DatatypeFactory.newInstance();
+ }
+
+ @DataProvider(name = "legal-number-duration")
+ public Object[][] getLegalNumberDuration() {
+ return new Object[][] {
+ // is positive, year, month, day, hour, minute, second
+ { true, 1, 1, 1, 1, 1, 1 },
+ { false, 1, 1, 1, 1, 1, 1 },
+ { true, 1, 0, 0, 0, 0, 0 },
+ { false, 1, 0, 0, 0, 0, 0 }
+ };
+ }
+
+ /*
+ * Test for constructor Duration(boolean isPositive,int years,int months,
+ * int days,int hours,int minutes,int seconds).
+ */
+ @Test(dataProvider = "legal-number-duration")
+ public void checkNumberDurationPos(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds) {
+ datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
+ }
+
+ @DataProvider(name = "illegal-number-duration")
+ public Object[][] getIllegalNumberDuration() {
+ return new Object[][] {
+ // is positive, year, month, day, hour, minute, second
+ { true, 1, 1, -1, 1, 1, 1 },
+ { false, 1, 1, -1, 1, 1, 1 },
+ { true, undef, undef, undef, undef, undef, undef },
+ { false, undef, undef, undef, undef, undef, undef }
+ };
+ }
+
+ /*
+ * Test for constructor Duration(boolean isPositive,int years,int months,
+ * int days,int hours,int minutes,int seconds), if any of the fields is
+ * negative should throw IllegalArgumentException.
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegal-number-duration")
+ public void checkDurationNumberNeg(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds) {
+ datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
+ }
+
+ @DataProvider(name = "legal-bigint-duration")
+ public Object[][] getLegalBigIntegerDuration() {
+ return new Object[][] {
+ // is positive, year, month, day, hour, minute, second
+ { true, zero, zero, zero, zero, zero, new BigDecimal(zero) },
+ { false, zero, zero, zero, zero, zero, new BigDecimal(zero) },
+ { true, one, one, one, one, one, new BigDecimal(one) },
+ { false, one, one, one, one, one, new BigDecimal(one) },
+ { true, null, null, null, null, null, new BigDecimal(one) },
+ { false, null, null, null, null, null, new BigDecimal(one) } };
+ }
+
+ /*
+ * Test for constructor Duration(boolean isPositive,BigInteger
+ * years,BigInteger months, BigInteger days,BigInteger hours,BigInteger
+ * minutes,BigDecimal seconds).
+ */
+ @Test(dataProvider = "legal-bigint-duration")
+ public void checkBigIntegerDurationPos(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes,
+ BigDecimal seconds) {
+ datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
+ }
+
+ @DataProvider(name = "illegal-bigint-duration")
+ public Object[][] getIllegalBigIntegerDuration() {
+ return new Object[][] {
+ // is positive, year, month, day, hour, minute, second
+ { true, null, null, null, null, null, null },
+ { false, null, null, null, null, null, null }
+ };
+ }
+
+ /*
+ * Test for constructor Duration(boolean isPositive,BigInteger
+ * years,BigInteger months, BigInteger days,BigInteger hours,BigInteger
+ * minutes,BigDecimal seconds), if all the fields are null should throw
+ * IllegalArgumentException.
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "illegal-bigint-duration")
+ public void checkBigIntegerDurationNeg(boolean isPositive, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes,
+ BigDecimal seconds) {
+ datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
+ }
+
+ @DataProvider(name = "legal-millisec-duration")
+ public Object[][] getLegalMilliSecondDuration() {
+ return new Object[][] { { 1000000 }, { 0 }, { Long.MAX_VALUE }, { Long.MIN_VALUE }
+
+ };
+ }
+
+ /*
+ * Test for constructor Duration(long durationInMilliSeconds)
+ */
+ @Test(dataProvider = "legal-millisec-duration")
+ public void checkMilliSecondDuration(long millisec) {
+ datatypeFactory.newDuration(millisec);
+ }
+
+ @DataProvider(name = "legal-lexical-duration")
+ public Object[][] getLegalLexicalDuration() {
+ return new Object[][] { { "P1Y1M1DT1H1M1S" }, { "-P1Y1M1DT1H1M1S" } };
+ }
+
+ /*
+ * Test for constructor Duration(java.lang.String lexicalRepresentation)
+ */
+ @Test(dataProvider = "legal-lexical-duration")
+ public void checkLexicalDurationPos(String lexRepresentation) {
+ datatypeFactory.newDuration(lexRepresentation);
+ }
+
+ @DataProvider(name = "illegal-lexical-duration")
+ public Object[][] getIllegalLexicalDuration() {
+ return new Object[][] {
+ { null },
+ { "P1Y1M1DT1H1M1S " },
+ { " P1Y1M1DT1H1M1S" },
+ { "X1Y1M1DT1H1M1S" },
+ { "" },
+ { "P1Y2MT" } // The designator 'T' shall be absent if all of the time items are absent in "PnYnMnDTnHnMnS"
+ };
+ }
+
+ /*
+ * Test for constructor Duration(java.lang.String lexicalRepresentation),
+ * null should throw NullPointerException, invalid lex should throw
+ * IllegalArgumentException
+ */
+ @Test(expectedExceptions = { NullPointerException.class, IllegalArgumentException.class }, dataProvider = "illegal-lexical-duration")
+ public void checkLexicalDurationNeg(String lexRepresentation) {
+ datatypeFactory.newDuration(lexRepresentation);
+ }
+
+ @DataProvider(name = "equal-duration")
+ public Object[][] getEqualDurations() {
+ return new Object[][] { { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" } };
+ }
+
+ /*
+ * Test for compare() both durations valid and equal.
+ */
+ @Test(dataProvider = "equal-duration")
+ public void checkDurationEqual(String lexRepresentation1, String lexRepresentation2) {
+ Duration duration1 = datatypeFactory.newDuration(lexRepresentation1);
+ Duration duration2 = datatypeFactory.newDuration(lexRepresentation2);
+ assertTrue(duration1.equals(duration2));
+ }
+
+ @DataProvider(name = "greater-duration")
+ public Object[][] getGreaterDuration() {
+ return new Object[][] {
+ { "P1Y1M1DT1H1M2S", "P1Y1M1DT1H1M1S" },
+ { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M2S" },
+ { "P1Y1M1DT1H1M2S", "-P1Y1M1DT1H1M1S" },
+ { "-P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M2S" }, };
+ }
+
+ /*
+ * Test for compare() both durations valid and lhs > rhs.
+ */
+ @Test(dataProvider = "greater-duration")
+ public void checkDurationCompare(String lexRepresentation1, String lexRepresentation2) {
+ Duration duration1 = datatypeFactory.newDuration(lexRepresentation1);
+ Duration duration2 = datatypeFactory.newDuration(lexRepresentation2);
+ assertTrue(duration1.compare(duration2) == DatatypeConstants.GREATER);
+ }
+
+ @DataProvider(name = "not-equal-duration")
+ public Object[][] getNotEqualDurations() {
+ return new Object[][] {
+ { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S" },
+ { "P2Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" } };
+ }
+
+ /*
+ * Test for equals() both durations valid and lhs not equals rhs.
+ */
+ @Test(dataProvider = "not-equal-duration")
+ public void checkDurationNotEqual(String lexRepresentation1, String lexRepresentation2) {
+ Duration duration1 = datatypeFactory.newDuration(lexRepresentation1);
+ Duration duration2 = datatypeFactory.newDuration(lexRepresentation2);
+ Assert.assertNotEquals(duration1, duration2);
+ }
+
+ @DataProvider(name = "duration-sign")
+ public Object[][] getDurationAndSign() {
+ return new Object[][] {
+ { "P0Y0M0DT0H0M0S", 0 },
+ { "P1Y0M0DT0H0M0S", 1 },
+ { "-P1Y0M0DT0H0M0S", -1 } };
+ }
+
+ /*
+ * Test for Duration.getSign().
+ */
+ @Test(dataProvider = "duration-sign")
+ public void checkDurationSign(String lexRepresentation, int sign) {
+ Duration duration = datatypeFactory.newDuration(lexRepresentation);
+ assertEquals(duration.getSign(), sign);
+ }
+
+ /*
+ * Test for Duration.negate().
+ */
+ @Test
+ public void checkDurationNegate() {
+ Duration durationPos = datatypeFactory.newDuration("P1Y0M0DT0H0M0S");
+ Duration durationNeg = datatypeFactory.newDuration("-P1Y0M0DT0H0M0S");
+
+ assertEquals(durationPos.negate(), durationNeg);
+ assertEquals(durationNeg.negate(), durationPos);
+ assertEquals(durationPos.negate().negate(), durationPos);
+
+ }
+
+ /*
+ * Test for Duration.isShorterThan(Duration) and
+ * Duration.isLongerThan(Duration).
+ */
+ @Test
+ public void checkDurationShorterLonger() {
+ Duration shorter = datatypeFactory.newDuration("P1Y1M1DT1H1M1S");
+ Duration longer = datatypeFactory.newDuration("P2Y1M1DT1H1M1S");
+
+ assertTrue(shorter.isShorterThan(longer));
+ assertFalse(longer.isShorterThan(shorter));
+ assertFalse(shorter.isShorterThan(shorter));
+
+ assertTrue(longer.isLongerThan(shorter));
+ assertFalse(shorter.isLongerThan(longer));
+ assertFalse(shorter.isLongerThan(shorter));
+ }
+
+ /*
+ * Test for Duration.isSet().
+ */
+ @Test
+ public void checkDurationIsSet() {
+ Duration duration1 = datatypeFactory.newDuration(true, 1, 1, 1, 1, 1, 1);
+ Duration duration2 = datatypeFactory.newDuration(true, 0, 0, 0, 0, 0, 0);
+
+ assertTrue(duration1.isSet(YEARS));
+ assertTrue(duration1.isSet(MONTHS));
+ assertTrue(duration1.isSet(DAYS));
+ assertTrue(duration1.isSet(HOURS));
+ assertTrue(duration1.isSet(MINUTES));
+ assertTrue(duration1.isSet(SECONDS));
+
+ assertTrue(duration2.isSet(YEARS));
+ assertTrue(duration2.isSet(MONTHS));
+ assertTrue(duration2.isSet(DAYS));
+ assertTrue(duration2.isSet(HOURS));
+ assertTrue(duration2.isSet(MINUTES));
+ assertTrue(duration2.isSet(SECONDS));
+
+ Duration duration66 = datatypeFactory.newDuration(true, null, null, zero, null, null, null);
+ assertFalse(duration66.isSet(YEARS));
+ assertFalse(duration66.isSet(MONTHS));
+ assertFalse(duration66.isSet(HOURS));
+ assertFalse(duration66.isSet(MINUTES));
+ assertFalse(duration66.isSet(SECONDS));
+
+ Duration duration3 = datatypeFactory.newDuration("P1D");
+ assertFalse(duration3.isSet(YEARS));
+ assertFalse(duration3.isSet(MONTHS));
+ assertFalse(duration3.isSet(HOURS));
+ assertFalse(duration3.isSet(MINUTES));
+ assertFalse(duration3.isSet(SECONDS));
+ }
+
+ /*
+ * Test Duration.isSet(Field) throws NPE if the field parameter is null.
+ */
+ @Test(expectedExceptions = NullPointerException.class)
+ public void checkDurationIsSetNeg() {
+ Duration duration = datatypeFactory.newDuration(true, 0, 0, 0, 0, 0, 0);
+ duration.isSet(null);
+ }
+
+ /*
+ * Test for -getField(DatatypeConstants.Field) DatatypeConstants.Field is
+ * null - throws NPE.
+ */
+ @Test(expectedExceptions = NullPointerException.class)
+ public void checkDurationGetFieldNeg() {
+ Duration duration67 = datatypeFactory.newDuration("P1Y1M1DT1H1M1S");
+ duration67.getField(null);
+ }
+
+ @DataProvider(name = "duration-fields")
+ public Object[][] getDurationAndFields() {
+ return new Object[][] {
+ { "P1Y1M1DT1H1M1S", one, one, one, one, one, new BigDecimal(one) },
+ { "PT1M", null, null, null, null, one, null },
+ { "P1M", null, one, null, null, null, null } };
+ }
+
+ /*
+ * Test for Duration.getField(DatatypeConstants.Field).
+ */
+ @Test(dataProvider = "duration-fields")
+ public void checkDurationGetField(String lexRepresentation, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes,
+ BigDecimal seconds) {
+ Duration duration = datatypeFactory.newDuration(lexRepresentation);
+
+ assertEquals(duration.getField(YEARS), years);
+ assertEquals(duration.getField(MONTHS), months);
+ assertEquals(duration.getField(DAYS), days);
+ assertEquals(duration.getField(HOURS), hours);
+ assertEquals(duration.getField(MINUTES), minutes);
+ assertEquals(duration.getField(SECONDS), seconds);
+ }
+
+ @DataProvider(name = "number-string")
+ public Object[][] getNumberAndString() {
+ return new Object[][] {
+ // is positive, year, month, day, hour, minute, second, lexical
+ { true, 1, 1, 1, 1, 1, 1, "P1Y1M1DT1H1M1S" },
+ { false, 1, 1, 1, 1, 1, 1, "-P1Y1M1DT1H1M1S" },
+ { true, 0, 0, 0, 0, 0, 0, "P0Y0M0DT0H0M0S" },
+ { false, 0, 0, 0, 0, 0, 0, "P0Y0M0DT0H0M0S" }
+ };
+ }
+
+ /*
+ * Test for - toString().
+ */
+ @Test(dataProvider = "number-string")
+ public void checkDurationToString(boolean isPositive, int years, int months, int days, int hours, int minutes, int seconds, String lexical) {
+ Duration duration = datatypeFactory.newDuration(isPositive, years, months, days, hours, minutes, seconds);
+ assertEquals(duration.toString(), lexical);
+
+ assertEquals(datatypeFactory.newDuration(duration.toString()), duration);
+ }
+
+ @DataProvider(name = "duration-field")
+ public Object[][] getDurationAndField() {
+ Function<Duration, Integer> getyears = duration -> duration.getYears();
+ Function<Duration, Integer> getmonths = duration -> duration.getMonths();
+ Function<Duration, Integer> getdays = duration -> duration.getDays();
+ Function<Duration, Integer> gethours = duration -> duration.getHours();
+ Function<Duration, Integer> getminutes = duration -> duration.getMinutes();
+ Function<Duration, Integer> getseconds = duration -> duration.getSeconds();
+ return new Object[][] {
+ { "P1Y1M1DT1H1M1S", getyears, 1 },
+ { "P1M1DT1H1M1S", getyears, 0 },
+ { "P1Y1M1DT1H1M1S", getmonths, 1 },
+ { "P1Y1DT1H1M1S", getmonths, 0 },
+ { "P1Y1M1DT1H1M1S", getdays, 1 },
+ { "P1Y1MT1H1M1S", getdays, 0 },
+ { "P1Y1M1DT1H1M1S", gethours, 1 },
+ { "P1Y1M1DT1M1S", gethours, 0 },
+ { "P1Y1M1DT1H1M1S", getminutes, 1 },
+ { "P1Y1M1DT1H1S", getminutes, 0 },
+ { "P1Y1M1DT1H1M1S", getseconds, 1 },
+ { "P1Y1M1DT1H1M", getseconds, 0 },
+ { "P1Y1M1DT1H1M100000000S", getseconds, 100000000 }, };
+ }
+
+ /*
+ * Test for Duration.getYears(), getMonths(), etc.
+ */
+ @Test(dataProvider = "duration-field")
+ public void checkDurationGetOneField(String lexRepresentation, Function<Duration, Integer> getter, int value) {
+ Duration duration = datatypeFactory.newDuration(lexRepresentation);
+ assertEquals(getter.apply(duration).intValue(), value);
+ }
+
+ /*
+ * Test for - getField(SECONDS)
+ */
+ @Test
+ public void checkDurationGetSecondsField() {
+ Duration duration85 = datatypeFactory.newDuration("P1Y1M1DT1H1M100000000S");
+ assertEquals((duration85.getField(SECONDS)).intValue(), 100000000);
+ }
+
+ /*
+ * getTimeInMillis(java.util.Calendar startInstant) returns milliseconds
+ * between startInstant and startInstant plus this Duration.
+ */
+ @Test
+ public void checkDurationGetTimeInMillis() {
+ Duration duration86 = datatypeFactory.newDuration("PT1M1S");
+ Calendar calendar86 = Calendar.getInstance();
+ assertEquals(duration86.getTimeInMillis(calendar86), 61000);
+ }
+
+ /*
+ * getTimeInMillis(java.util.Calendar startInstant) returns milliseconds
+ * between startInstant and startInstant plus this Duration throws NPE if
+ * startInstant parameter is null.
+ */
+ @Test(expectedExceptions = NullPointerException.class)
+ public void checkDurationGetTimeInMillisNeg() {
+ Duration duration87 = datatypeFactory.newDuration("PT1M1S");
+ Calendar calendar87 = null;
+ duration87.getTimeInMillis(calendar87);
+ }
+
+ @DataProvider(name = "duration-for-hash")
+ public Object[][] getDurationsForHash() {
+ return new Object[][] {
+ { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S" },
+ { "P1D", "PT24H" },
+ { "PT1H", "PT60M" },
+ { "PT1M", "PT60S" },
+ { "P1Y", "P12M" } };
+ }
+
+ /*
+ * Test for Duration.hashcode(). hashcode() should return same value for
+ * some equal durations.
+ */
+ @Test(dataProvider = "duration-for-hash")
+ public void checkDurationHashCode(String lexRepresentation1, String lexRepresentation2) {
+ Duration duration1 = datatypeFactory.newDuration(lexRepresentation1);
+ Duration duration2 = datatypeFactory.newDuration(lexRepresentation2);
+ int hash1 = duration1.hashCode();
+ int hash2 = duration2.hashCode();
+ assertTrue(hash1 == hash2, " generated hash1 : " + hash1 + " generated hash2 : " + hash2);
+ }
+
+ @DataProvider(name = "duration-for-add")
+ public Object[][] getDurationsForAdd() {
+ return new Object[][] {
+ // initVal, addVal, resultVal
+ { "P1Y1M1DT1H1M1S", "P1Y1M1DT1H1M1S", "P2Y2M2DT2H2M2S" },
+ { "P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S", "P0Y0M0DT0H0M0S" },
+ { "-P1Y1M1DT1H1M1S", "-P1Y1M1DT1H1M1S", "-P2Y2M2DT2H2M2S" }, };
+ }
+
+ /*
+ * Test for add(Duration rhs).
+ */
+ @Test(dataProvider = "duration-for-add")
+ public void checkDurationAdd(String initVal, String addVal, String result) {
+ Duration durationInit = datatypeFactory.newDuration(initVal);
+ Duration durationAdd = datatypeFactory.newDuration(addVal);
+ Duration durationResult = datatypeFactory.newDuration(result);
+
+ assertEquals(durationInit.add(durationAdd), durationResult);
+ }
+
+ @DataProvider(name = "duration-for-addneg")
+ public Object[][] getDurationsForAddNeg() {
+ return new Object[][] {
+ // initVal, addVal
+ { "P1Y1M1DT1H1M1S", null },
+ { "P1Y", "-P1D" },
+ { "-P1Y", "P1D" }, };
+ }
+
+ /*
+ * Test for add(Duration rhs) 'rhs' is null , should throw NPE. "1 year" +
+ * "-1 day" or "-1 year" + "1 day" should throw IllegalStateException
+ */
+ @Test(expectedExceptions = { NullPointerException.class, IllegalStateException.class }, dataProvider = "duration-for-addneg")
+ public void checkDurationAddNeg(String initVal, String addVal) {
+ Duration durationInit = datatypeFactory.newDuration(initVal);
+ Duration durationAdd = addVal == null ? null : datatypeFactory.newDuration(addVal);
+
+ durationInit.add(durationAdd);
+ }
+
+ /*
+ * Test Duration#compare(Duration duration) with large durations.
+ *
+ * Bug # 4972785 UnsupportedOperationException is expected
+ *
+ */
+ @Test(expectedExceptions = UnsupportedOperationException.class)
+ public void checkDurationCompareLarge() {
+ String duration1Lex = "P100000000000000000000D";
+ String duration2Lex = "PT2400000000000000000000H";
+
+ Duration duration1 = datatypeFactory.newDuration(duration1Lex);
+ Duration duration2 = datatypeFactory.newDuration(duration2Lex);
+ duration1.compare(duration2);
+
+ }
+
+ /*
+ * Test Duration#getXMLSchemaType().
+ *
+ * Bug # 5049544 Duration.getXMLSchemaType shall return the correct result
+ *
+ */
+ @Test
+ public void checkDurationGetXMLSchemaType() {
+ // DURATION
+ Duration duration = datatypeFactory.newDuration("P1Y1M1DT1H1M1S");
+ QName duration_xmlSchemaType = duration.getXMLSchemaType();
+ assertEquals(duration_xmlSchemaType, DatatypeConstants.DURATION, "Expected DatatypeConstants.DURATION, returned " + duration_xmlSchemaType.toString());
+
+ // DURATION_DAYTIME
+ Duration duration_dayTime = datatypeFactory.newDuration("P1DT1H1M1S");
+ QName duration_dayTime_xmlSchemaType = duration_dayTime.getXMLSchemaType();
+ assertEquals(duration_dayTime_xmlSchemaType, DatatypeConstants.DURATION_DAYTIME, "Expected DatatypeConstants.DURATION_DAYTIME, returned "
+ + duration_dayTime_xmlSchemaType.toString());
+
+ // DURATION_YEARMONTH
+ Duration duration_yearMonth = datatypeFactory.newDuration("P1Y1M");
+ QName duration_yearMonth_xmlSchemaType = duration_yearMonth.getXMLSchemaType();
+ assertEquals(duration_yearMonth_xmlSchemaType, DatatypeConstants.DURATION_YEARMONTH, "Expected DatatypeConstants.DURATION_YEARMONTH, returned "
+ + duration_yearMonth_xmlSchemaType.toString());
+
+ }
+
+
+ private final int undef = DatatypeConstants.FIELD_UNDEFINED;
+ private final BigInteger zero = BigInteger.ZERO;
+ private final BigInteger one = BigInteger.ONE;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/FactoryNewInstanceTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.datatype.ptests;
+
+import static org.testng.Assert.assertNotNull;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+
+import jaxp.library.JAXPDataProvider;
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @summary Tests for DatatypeFactory.newInstance(factoryClassName , classLoader)
+ */
+public class FactoryNewInstanceTest extends JAXPBaseTest {
+
+ private static final String DATATYPE_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.datatype.DatatypeFactoryImpl";
+
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { DATATYPE_FACTORY_CLASSNAME, null }, { DATATYPE_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /*
+ * test for DatatypeFactory.newInstance(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName points to correct
+ * implementation of javax.xml.datatype.DatatypeFactory , should return
+ * newInstance of DatatypeFactory
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String factoryClassName, ClassLoader classLoader) throws DatatypeConfigurationException {
+ DatatypeFactory dtf = DatatypeFactory.newInstance(DATATYPE_FACTORY_CLASSNAME, null);
+ Duration duration = dtf.newDuration(true, 1, 1, 1, 1, 1, 1);
+ assertNotNull(duration);
+ }
+
+
+ /*
+ * test for DatatypeFactory.newInstance(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName is null , should
+ * throw DatatypeConfigurationException
+ */
+ @Test(expectedExceptions = DatatypeConfigurationException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceNeg(String factoryClassName, ClassLoader classLoader) throws DatatypeConfigurationException {
+ DatatypeFactory.newInstance(factoryClassName, classLoader);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/datatype/ptests/XMLGregorianCalendarTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.datatype.ptests;
+
+import static java.util.Calendar.HOUR;
+import static java.util.Calendar.MINUTE;
+import static java.util.Calendar.YEAR;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.Duration;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @bug 5049592 5041845 5048932 5064587 5040542 5049531 5049528
+ * @summary Class containing the test cases for XMLGregorianCalendar
+ */
+public class XMLGregorianCalendarTest extends JAXPBaseTest {
+
+ private DatatypeFactory datatypeFactory;
+
+ @BeforeClass
+ public void setup() throws DatatypeConfigurationException {
+ datatypeFactory = DatatypeFactory.newInstance();
+ }
+
+ @DataProvider(name = "valid-milliseconds")
+ public Object[][] getValidMilliSeconds() {
+ return new Object[][] { { 0 }, { 1 }, { 2 }, { 16 }, { 1000 } };
+ }
+
+ /*
+ * Test DatatypeFactory.newXMLGregorianCalendar(..) with milliseconds > 1.
+ *
+ * Bug # 5049592
+ *
+ */
+ @Test(dataProvider = "valid-milliseconds")
+ public void checkNewCalendar(int ms) {
+ // valid milliseconds
+ XMLGregorianCalendar calendar = datatypeFactory.newXMLGregorianCalendar(2004, // year
+ 6, // month
+ 2, // day
+ 19, // hour
+ 20, // minute
+ 59, // second
+ ms, // milliseconds
+ 840 // timezone
+ );
+ // expected success
+
+ assertEquals(calendar.getMillisecond(), ms);
+ }
+
+ /*
+ * Test DatatypeFactory.newXMLGregorianCalendarTime(..).
+ *
+ * Bug # 5049592
+ */
+ @Test(dataProvider = "valid-milliseconds")
+ public void checkNewTime(int ms) {
+ // valid milliseconds
+ XMLGregorianCalendar calendar2 = datatypeFactory.newXMLGregorianCalendarTime(19, // hour
+ 20, // minute
+ 59, // second
+ ms, // milliseconds
+ 840 // timezone
+ );
+ // expected success
+
+ assertEquals(calendar2.getMillisecond(), ms);
+ }
+
+ @DataProvider(name = "invalid-milliseconds")
+ public Object[][] getInvalidMilliSeconds() {
+ return new Object[][] { { -1 }, { 1001 } };
+ }
+
+ /*
+ * Test DatatypeFactory.newXMLGregorianCalendar(..).
+ *
+ * Bug # 5049592 IllegalArgumentException is thrown if milliseconds < 0 or >
+ * 1001.
+ *
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "invalid-milliseconds")
+ public void checkNewCalendarNeg(int milliseconds) {
+ // invalid milliseconds
+ datatypeFactory.newXMLGregorianCalendar(2004, // year
+ 6, // month
+ 2, // day
+ 19, // hour
+ 20, // minute
+ 59, // second
+ milliseconds, // milliseconds
+ 840 // timezone
+ );
+ }
+
+ /*
+ * Test DatatypeFactory.newXMLGregorianCalendarTime(..).
+ *
+ * Bug # 5049592 IllegalArgumentException is thrown if milliseconds < 0 or >
+ * 1001.
+ *
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "invalid-milliseconds")
+ public void checkNewTimeNeg(int milliseconds) {
+ // invalid milliseconds
+ datatypeFactory.newXMLGregorianCalendarTime(19, // hour
+ 20, // minute
+ 59, // second
+ milliseconds, // milliseconds
+ 840 // timezone
+ );
+ }
+
+ @DataProvider(name = "data-for-add")
+ public Object[][] getDataForAdd() {
+ return new Object[][] {
+ //calendar1, calendar2, duration
+ { "1999-12-31T00:00:00Z", "2000-01-01T00:00:00Z", "P1D" },
+ { "2000-12-31T00:00:00Z", "2001-01-01T00:00:00Z", "P1D" },
+ { "1998-12-31T00:00:00Z", "1999-01-01T00:00:00Z", "P1D" },
+ { "2001-12-31T00:00:00Z", "2002-01-01T00:00:00Z", "P1D" },
+ { "2003-04-11T00:00:00Z", "2003-04-12T00:00:00Z", "P1D" },
+ { "2003-04-11T00:00:00Z", "2003-04-14T00:00:00Z", "P3D" },
+ { "2003-04-30T00:00:00Z", "2003-05-01T00:00:00Z", "P1D" },
+ { "2003-02-28T00:00:00Z", "2003-03-01T00:00:00Z", "P1D" },
+ { "2000-02-29T00:00:00Z", "2000-03-01T00:00:00Z", "P1D" },
+ { "2000-02-28T00:00:00Z", "2000-02-29T00:00:00Z", "P1D" },
+ { "1998-01-11T00:00:00Z", "1998-04-11T00:00:00Z", "P90D" },
+ { "1999-05-11T00:00:00Z", "2002-05-11T00:00:00Z", "P1096D" }};
+ }
+
+ /*
+ * Test XMLGregorianCalendar.add(Duration).
+ *
+ */
+ @Test(dataProvider = "data-for-add")
+ public void checkAddDays(String cal1, String cal2, String dur) {
+
+ XMLGregorianCalendar calendar1 = datatypeFactory.newXMLGregorianCalendar(cal1);
+ XMLGregorianCalendar calendar2 = datatypeFactory.newXMLGregorianCalendar(cal2);
+
+ Duration duration = datatypeFactory.newDuration(dur);
+
+ XMLGregorianCalendar calendar1Clone = (XMLGregorianCalendar)calendar1.clone();
+
+ calendar1Clone.add(duration);
+ assertEquals(calendar1Clone, calendar2);
+
+ calendar2.add(duration.negate());
+ assertEquals(calendar2, calendar1);
+
+ }
+
+ @DataProvider(name = "gMonth")
+ public Object[][] getGMonth() {
+ return new Object[][] {
+ { "2000-02" },
+ { "2000-03" },
+ { "2018-02" }};
+ }
+ /*
+ * Test XMLGregorianCalendar#isValid(). for gMonth
+ *
+ * Bug # 5041845
+ *
+ */
+ @Test(dataProvider = "gMonth")
+ public void checkIsValid(String month) {
+
+ XMLGregorianCalendar gMonth = datatypeFactory.newXMLGregorianCalendar(month);
+ gMonth.setYear(null);
+ Assert.assertTrue(gMonth.isValid(), gMonth.toString() + " should isValid");
+
+ }
+
+ @DataProvider(name = "lexical01")
+ public Object[][] getLexicalRepresentForNormalize01() {
+ return new Object[][] { { "2000-01-16T12:00:00Z" }, { "2000-01-16T12:00:00" } };
+ }
+
+ /*
+ * Test XMLGregorianCalendar#normalize(...).
+ *
+ * Bug # 5048932 XMLGregorianCalendar.normalize works
+ *
+ */
+ @Test(dataProvider = "lexical01")
+ public void checkNormalize01(String lexical) {
+ XMLGregorianCalendar lhs = datatypeFactory.newXMLGregorianCalendar(lexical);
+ lhs.normalize();
+ }
+
+ @DataProvider(name = "lexical02")
+ public Object[][] getLexicalRepresentForNormalize02() {
+ return new Object[][] { { "2000-01-16T00:00:00.01Z" }, { "2000-01-16T00:00:00.01" }, { "13:20:00" } };
+ }
+
+ /*
+ * Test XMLGregorianCalendar#normalize(...).
+ *
+ * Bug # 5064587 XMLGregorianCalendar.normalize shall not change timezone
+ *
+ */
+ @Test(dataProvider = "lexical02")
+ public void checkNormalize02(String lexical) {
+ XMLGregorianCalendar orig = datatypeFactory.newXMLGregorianCalendar(lexical);
+ XMLGregorianCalendar normalized = datatypeFactory.newXMLGregorianCalendar(lexical).normalize();
+
+ assertEquals(normalized.getTimezone(), orig.getTimezone());
+ assertEquals(normalized.getMillisecond(), orig.getMillisecond());
+ }
+
+ /*
+ * Test XMLGregorianCalendar#toGregorianCalendar( TimeZone timezone, Locale
+ * aLocale, XMLGregorianCalendar defaults)
+ *
+ * Bug # 5040542 the defaults XMLGregorianCalendar parameter shall take
+ * effect
+ *
+ */
+ @Test
+ public void checkToGregorianCalendar01() {
+
+ XMLGregorianCalendar time_16_17_18 = datatypeFactory.newXMLGregorianCalendar("16:17:18");
+ XMLGregorianCalendar date_2001_02_03 = datatypeFactory.newXMLGregorianCalendar("2001-02-03");
+ GregorianCalendar calendar = date_2001_02_03.toGregorianCalendar(null, null, time_16_17_18);
+
+ int year = calendar.get(YEAR);
+ int minute = calendar.get(MINUTE);
+
+ assertTrue((year == 2001 && minute == 17), " expecting year == 2001, minute == 17" + ", result is year == " + year + ", minute == " + minute);
+
+
+ calendar = time_16_17_18.toGregorianCalendar(null, null, date_2001_02_03);
+
+ year = calendar.get(YEAR);
+ minute = calendar.get(MINUTE);
+
+ assertTrue((year == 2001 && minute == 17), " expecting year == 2001, minute == 17" + ", result is year == " + year + ", minute == " + minute);
+
+
+ date_2001_02_03.setMinute(3);
+ date_2001_02_03.setYear(null);
+
+ XMLGregorianCalendar date_time = datatypeFactory.newXMLGregorianCalendar("2003-04-11T02:13:01Z");
+
+ calendar = date_2001_02_03.toGregorianCalendar(null, null, date_time);
+
+ year = calendar.get(YEAR);
+ minute = calendar.get(MINUTE);
+ int hour = calendar.get(HOUR);
+
+ assertTrue((year == 2003 && hour == 2 && minute == 3), " expecting year == 2003, hour == 2, minute == 3" + ", result is year == " + year + ", hour == " + hour + ", minute == " + minute);
+
+
+ }
+
+ /*
+ * Test XMLGregorianCalendar#toGregorianCalendar( TimeZone timezone, Locale
+ * aLocale, XMLGregorianCalendar defaults) with the 'defaults' parameter
+ * being null.
+ *
+ * Bug # 5049531 XMLGregorianCalendar.toGregorianCalendar(..) can accept
+ * 'defaults' is null
+ *
+ */
+ @Test
+ public void checkToGregorianCalendar02() {
+
+ XMLGregorianCalendar calendar = datatypeFactory.newXMLGregorianCalendar("2004-05-19T12:00:00+06:00");
+ calendar.toGregorianCalendar(TimeZone.getDefault(), Locale.getDefault(), null);
+ }
+
+ @DataProvider(name = "calendar")
+ public Object[][] getXMLGregorianCalendarData() {
+ return new Object[][] {
+ // year, month, day, hour, minute, second
+ { 1970, 1, 1, 0, 0, 0 }, // DATETIME
+ { 1970, 1, 1, undef, undef, undef }, // DATE
+ { undef, undef, undef, 1, 0, 0 }, // TIME
+ { 1970, 1, undef, undef, undef, undef }, // GYEARMONTH
+ { undef, 1, 1, undef, undef, undef }, // GMONTHDAY
+ { 1970, undef, undef, undef, undef, undef }, // GYEAR
+ { undef, 1, undef, undef, undef, undef }, // GMONTH
+ { undef, undef, 1, undef, undef, undef } // GDAY
+ };
+ }
+
+ /*
+ * Test XMLGregorianCalendar#toString()
+ *
+ * Bug # 5049528
+ *
+ */
+ @Test(dataProvider = "calendar")
+ public void checkToStringPos(final int year, final int month, final int day, final int hour, final int minute, final int second) {
+ XMLGregorianCalendar calendar = datatypeFactory.newXMLGregorianCalendar(year, month, day, hour, minute, second, undef, undef);
+ calendar.toString();
+ }
+
+ /*
+ * Negative Test XMLGregorianCalendar#toString()
+ *
+ * Bug # 5049528 XMLGregorianCalendar.toString throws IllegalStateException
+ * if all parameters are undef
+ *
+ */
+ @Test(expectedExceptions = IllegalStateException.class)
+ public void checkToStringNeg() {
+ XMLGregorianCalendar calendar = datatypeFactory.newXMLGregorianCalendar(undef, undef, undef, undef, undef, undef, undef, undef);
+ // expected to fail
+ calendar.toString();
+ }
+
+ private final int undef = DatatypeConstants.FIELD_UNDEFINED;
+
+}
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/DocumentBuilderFactoryTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -26,27 +26,38 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilePermission;
import java.io.FileReader;
+
import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+
import static javax.xml.parsers.ptests.ParserTestConst.GOLDEN_DIR;
import static javax.xml.parsers.ptests.ParserTestConst.XML_DIR;
+
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
+
+import jaxp.library.JAXPDataProvider;
import jaxp.library.JAXPFileBaseTest;
import static jaxp.library.JAXPTestUtilities.USER_DIR;
import static jaxp.library.JAXPTestUtilities.compareWithGold;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -60,6 +71,52 @@
*/
public class DocumentBuilderFactoryTest extends JAXPFileBaseTest {
/**
+ * DocumentBuilderFactory implementation class name.
+ */
+ private static final String DOCUMENT_BUILDER_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
+
+ /**
+ * Provide valid DocumentBuilderFactory instantiation parameters.
+ *
+ * @return a data provider contains DocumentBuilderFactory instantiation parameters.
+ */
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { DOCUMENT_BUILDER_FACTORY_CLASSNAME, null }, { DOCUMENT_BUILDER_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /**
+ * Test for DocumentBuilderFactory.newInstance(java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
+ * points to correct implementation of
+ * javax.xml.parsers.DocumentBuilderFactory , should return newInstance of
+ * DocumentBuilderFactory
+ *
+ * @param factoryClassName
+ * @param classLoader
+ * @throws ParserConfigurationException
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String factoryClassName, ClassLoader classLoader) throws ParserConfigurationException {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(factoryClassName, classLoader);
+ DocumentBuilder builder = dbf.newDocumentBuilder();
+ assertNotNull(builder);
+ }
+
+ /**
+ * test for DocumentBuilderFactory.newInstance(java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName is
+ * null , should throw FactoryConfigurationError
+ *
+ * @param factoryClassName
+ * @param classLoader
+ */
+ @Test(expectedExceptions = FactoryConfigurationError.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceNeg(String factoryClassName, ClassLoader classLoader) {
+ DocumentBuilderFactory.newInstance(factoryClassName, classLoader);
+ }
+
+ /**
* Test the default functionality of schema support method.
* @throws Exception If any errors occur.
*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXFactoryNewInstanceTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.parsers.ptests;
+
+import static org.testng.Assert.assertNotNull;
+
+import javax.xml.parsers.FactoryConfigurationError;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import jaxp.library.JAXPDataProvider;
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary Tests for SAXParserFactory.newInstance(factoryClassName , classLoader)
+ */
+public class SAXFactoryNewInstanceTest extends JAXPBaseTest {
+
+ private static final String SAXPARSER_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl";
+
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { SAXPARSER_FACTORY_CLASSNAME, null }, { SAXPARSER_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /*
+ * test for SAXParserFactory.newInstance(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName points to correct
+ * implementation of javax.xml.parsers.SAXParserFactory , should return
+ * newInstance of SAXParserFactory
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String factoryClassName, ClassLoader classLoader) throws ParserConfigurationException, SAXException {
+ SAXParserFactory spf = SAXParserFactory.newInstance(factoryClassName, classLoader);
+ SAXParser sp = spf.newSAXParser();
+ assertNotNull(sp);
+ }
+
+ /*
+ * test for SAXParserFactory.newInstance(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName is null , should
+ * throw FactoryConfigurationError
+ */
+ @Test(expectedExceptions = FactoryConfigurationError.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceNeg(String factoryClassName, ClassLoader classLoader) {
+ SAXParserFactory.newInstance(factoryClassName, classLoader);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLEventFactoryNewInstanceTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.stream.ptests;
+
+import static org.testng.Assert.assertNotNull;
+
+import javax.xml.stream.XMLEventFactory;
+
+import jaxp.library.JAXPDataProvider;
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @summary Tests for XMLEventFactory.newFactory(factoryId , classLoader)
+ */
+public class XMLEventFactoryNewInstanceTest extends JAXPBaseTest {
+
+ private static final String XMLEVENT_FACTORY_CLASSNAME = "com.sun.xml.internal.stream.events.XMLEventFactoryImpl";
+ private static final String XMLEVENT_FACRORY_ID = "javax.xml.stream.XMLEventFactory";
+
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { XMLEVENT_FACRORY_ID, null }, { XMLEVENT_FACRORY_ID, this.getClass().getClassLoader() } };
+ }
+
+ /*
+ * test for XMLEventFactory.newFactory(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName points to correct
+ * implementation of javax.xml.stream.XMLEventFactory , should return
+ * newInstance of XMLEventFactory
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewFactory(String factoryId, ClassLoader classLoader) {
+ setSystemProperty(XMLEVENT_FACRORY_ID, XMLEVENT_FACTORY_CLASSNAME);
+ try {
+ XMLEventFactory xef = XMLEventFactory.newFactory(factoryId, classLoader);
+ assertNotNull(xef);
+ } finally {
+ setSystemProperty(XMLEVENT_FACRORY_ID, null);
+ }
+ }
+
+ /*
+ * test for XMLEventFactory.newFactory(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName is null , should
+ * throw NullPointerException
+ */
+ @Test(expectedExceptions = NullPointerException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewFactoryNeg(String factoryId, ClassLoader classLoader) {
+ XMLEventFactory.newFactory(null, null);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/stream/ptests/XMLInputFactoryNewInstanceTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.stream.ptests;
+
+import static org.testng.Assert.assertNotNull;
+
+import javax.xml.stream.XMLInputFactory;
+
+import jaxp.library.JAXPDataProvider;
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @summary Tests for XMLInputFactory.newFactory(factoryId , classLoader)
+ */
+public class XMLInputFactoryNewInstanceTest extends JAXPBaseTest {
+
+ private static final String XMLINPUT_FACTORY_CLASSNAME = "com.sun.xml.internal.stream.XMLInputFactoryImpl";
+ private static final String XMLINPUT_FACRORY_ID = "javax.xml.stream.XMLInputFactory";
+
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { XMLINPUT_FACRORY_ID, null }, { XMLINPUT_FACRORY_ID, this.getClass().getClassLoader() } };
+ }
+
+ /*
+ * test for XMLInputFactory.newFactory(java.lang.String factoryId,
+ * java.lang.ClassLoader classLoader) factoryClassName points to correct
+ * implementation of javax.xml.stream.XMLInputFactory , should return
+ * newInstance of XMLInputFactory
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewFactory(String factoryId, ClassLoader classLoader) {
+ setSystemProperty(XMLINPUT_FACRORY_ID, XMLINPUT_FACTORY_CLASSNAME);
+ try {
+ XMLInputFactory xif = XMLInputFactory.newFactory(factoryId, classLoader);
+ assertNotNull(xif);
+ } finally {
+ setSystemProperty(XMLINPUT_FACRORY_ID, null);
+ }
+ }
+
+ /*
+ * test for XMLInputFactory.newFactory(java.lang.String factoryClassName,
+ * java.lang.ClassLoader classLoader) factoryClassName is null , should
+ * throw NullPointerException
+ */
+ @Test(expectedExceptions = NullPointerException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewFactoryNeg(String factoryId, ClassLoader classLoader) {
+ XMLInputFactory.newFactory(factoryId, classLoader);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/Bug6384418Test.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.transform.ptests;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPFileBaseTest;
+import static javax.xml.transform.ptests.TransformerTestConst.XML_DIR;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+
+/*
+ * @bug 6384418
+ * @summary verify the transforming won't throw any exception
+ */
+public class Bug6384418Test extends JAXPFileBaseTest {
+
+ @Test
+ public void test() throws Exception {
+ TransformerFactory tfactory = TransformerFactory.newInstance();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document document = db.parse(new File(XML_DIR + "dataentry.xsl"));
+ DOMSource domSource = new DOMSource(document);
+
+ Transformer transformer = tfactory.newTransformer(domSource);
+ StreamSource streamSource = new StreamSource(new File(XML_DIR + "test.xml"));
+ StreamResult streamResult = new StreamResult(new ByteArrayOutputStream());
+ transformer.transform(streamSource, streamResult);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.transform.ptests;
+
+import static javax.xml.transform.ptests.TransformerTestConst.XML_DIR;
+
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.function.Supplier;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stax.StAXResult;
+import javax.xml.transform.stax.StAXSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+
+/*
+ * @summary Tests for variable combination of Transformer.transform(Source, Result)
+ */
+@Test(singleThreaded = true)
+public class TransformTest extends JAXPFileBaseTest {
+
+ /*
+ * Initialize the share objects.
+ */
+ @BeforeClass
+ public void setup() throws Exception {
+ ifac = XMLInputFactory.newInstance();
+ ofac = XMLOutputFactory.newInstance();
+ tfac = TransformerFactory.newInstance();
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ db = dbf.newDocumentBuilder();
+
+ xml = Files.readAllBytes(Paths.get(XML_DIR + "cities.xml"));
+ template = Files.readAllBytes(Paths.get(XML_DIR + "cities.xsl"));
+
+ xmlDoc = db.parse(xmlInputStream());
+ }
+
+ @DataProvider(name = "input-provider")
+ public Object[][] prepareTestCombination() throws Exception {
+
+ Supplier<Source> staxStreamSource = () -> new StAXSource(getXMLStreamReader());
+ Supplier<Source> staxEventSource = this::getStAXEventSource;
+ Supplier<Source> domSource = () -> new DOMSource(xmlDoc);
+ Supplier<Source> saxSource = () -> new SAXSource(new InputSource(xmlInputStream()));
+ Supplier<Source> streamSource = () -> new StreamSource(xmlInputStream());
+
+ Supplier<Result> staxStreamResult = () -> new StAXResult(getXMLStreamWriter());
+ Supplier<Result> staxEventResult = () -> new StAXResult(getXMLEventWriter());
+ Supplier<Result> saxResult = this::getHandlerSAXResult;
+ Supplier<Result> streamResult = () -> new StreamResult(transOutputStream());
+
+ Transformer domTemplateTransformer = createTransformer(getDomTemplate());
+ Transformer saxTemplateTransformer = createTransformer(getSAXTemplate());
+ Transformer streamTemplateTransformer = createTransformer(getStreamTemplate());
+ Transformer noTemplateTransformer = createTransformer(null);
+ Transformer staxStreamTemplateTransformer = createTransformer(getStAXStreamTemplate());
+ Transformer staxEventTemplateTransformer = createTransformer(getStAXEventTemplate());
+
+ return new Object[][] {
+ // StAX Stream
+ { staxStreamSource, staxStreamResult, domTemplateTransformer },
+ { staxStreamSource, staxStreamResult, saxTemplateTransformer },
+ { staxStreamSource, staxStreamResult, streamTemplateTransformer },
+ { staxStreamSource, staxStreamResult, noTemplateTransformer },
+ { staxStreamSource, staxStreamResult, staxStreamTemplateTransformer },
+ { staxStreamSource, saxResult, domTemplateTransformer },
+ { staxStreamSource, streamResult, domTemplateTransformer },
+ { domSource, staxStreamResult, domTemplateTransformer },
+ { saxSource, staxStreamResult, domTemplateTransformer },
+ { streamSource, staxStreamResult, domTemplateTransformer },
+ { staxStreamSource, streamResult, saxTemplateTransformer },
+ { domSource, staxStreamResult, saxTemplateTransformer },
+ { saxSource, staxStreamResult, saxTemplateTransformer },
+ { streamSource, staxStreamResult, saxTemplateTransformer },
+ { staxStreamSource, streamResult, streamTemplateTransformer },
+ { domSource, staxStreamResult, streamTemplateTransformer },
+ { saxSource, staxStreamResult, streamTemplateTransformer },
+ { streamSource, staxStreamResult, streamTemplateTransformer },
+ // StAX Event
+ { staxEventSource, staxEventResult, domTemplateTransformer },
+ { staxEventSource, staxEventResult, saxTemplateTransformer },
+ { staxEventSource, staxEventResult, streamTemplateTransformer },
+ { staxEventSource, staxEventResult, noTemplateTransformer },
+ { staxEventSource, staxEventResult, staxEventTemplateTransformer },
+ { staxEventSource, saxResult, domTemplateTransformer },
+ { staxEventSource, streamResult, domTemplateTransformer },
+ { domSource, staxEventResult, domTemplateTransformer },
+ { saxSource, staxEventResult, domTemplateTransformer },
+ { streamSource, staxEventResult, domTemplateTransformer },
+ { staxEventSource, streamResult, saxTemplateTransformer },
+ { domSource, staxEventResult, saxTemplateTransformer },
+ { saxSource, staxEventResult, saxTemplateTransformer },
+ { streamSource, staxEventResult, saxTemplateTransformer },
+ { staxEventSource, streamResult, streamTemplateTransformer },
+ { domSource, staxEventResult, streamTemplateTransformer },
+ { saxSource, staxEventResult, streamTemplateTransformer },
+ { streamSource, staxEventResult, streamTemplateTransformer } };
+ }
+
+ /*
+ * run Transformer.transform(Source, Result)
+ */
+ @Test(dataProvider = "input-provider")
+ public void testTransform(Supplier<Source> src, Supplier<Result> res, Transformer transformer) throws Throwable {
+ try {
+ transformer.transform(src.get(), res.get());
+ } catch (WrapperException e) {
+ throw e.getCause();
+ }
+ }
+
+ private InputStream xmlInputStream() {
+ return new ByteArrayInputStream(xml);
+ }
+
+ private InputStream templateInputStream() {
+ return new ByteArrayInputStream(template);
+ }
+
+ private OutputStream transOutputStream() {
+ return new ByteArrayOutputStream(xml.length);
+ }
+
+ private XMLStreamReader getXMLStreamReader() {
+ try {
+ return ifac.createXMLStreamReader(xmlInputStream());
+ } catch (XMLStreamException e) {
+ throw new WrapperException(e);
+ }
+ }
+
+ private XMLStreamWriter getXMLStreamWriter() {
+ try {
+ return ofac.createXMLStreamWriter(transOutputStream());
+ } catch (XMLStreamException e) {
+ throw new WrapperException(e);
+ }
+ }
+
+ private StAXSource getStAXEventSource() {
+ try {
+ return new StAXSource(ifac.createXMLEventReader(xmlInputStream()));
+ } catch (XMLStreamException e) {
+ throw new WrapperException(e);
+ }
+ }
+
+ private XMLEventWriter getXMLEventWriter() {
+ try {
+ return ofac.createXMLEventWriter(transOutputStream());
+ } catch (XMLStreamException e) {
+ throw new WrapperException(e);
+ }
+ }
+
+ private SAXResult getHandlerSAXResult() {
+ SAXResult res = new SAXResult();
+ MyContentHandler myContentHandler = new MyContentHandler(transOutputStream());
+ res.setHandler(myContentHandler);
+ return res;
+ }
+
+ private Source getDomTemplate() throws SAXException, IOException {
+ return new DOMSource(db.parse(templateInputStream()));
+ }
+
+ private Source getSAXTemplate() {
+ return new SAXSource(new InputSource(templateInputStream()));
+ }
+
+ private Source getStreamTemplate() {
+ return new StreamSource(templateInputStream());
+ }
+
+ private Source getStAXStreamTemplate() throws XMLStreamException {
+ return new StAXSource(ifac.createXMLStreamReader(templateInputStream()));
+ }
+
+ private Source getStAXEventTemplate() throws XMLStreamException {
+ return new StAXSource(ifac.createXMLEventReader(templateInputStream()));
+ }
+
+ private Transformer createTransformer(Source templateSource) throws TransformerConfigurationException {
+ Transformer transformer = (templateSource == null) ? tfac.newTransformer() : tfac.newTransformer(templateSource);
+ transformer.setOutputProperty("indent", "yes");
+ return transformer;
+
+ }
+
+ private static class MyContentHandler implements ContentHandler {
+ private BufferedWriter bWriter;
+
+ public MyContentHandler(OutputStream os) {
+ bWriter = new BufferedWriter(new OutputStreamWriter(os));
+ }
+
+ public void setDocumentLocator(Locator locator) {
+ }
+
+ public void startDocument() throws SAXException {
+ String str = "startDocument";
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void endDocument() throws SAXException {
+ String str = "endDocument";
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ bWriter.flush();
+ bWriter.close();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ String str = "startPrefixMapping: " + prefix + ", " + uri;
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void endPrefixMapping(String prefix) throws SAXException {
+ String str = "endPrefixMapping: " + prefix;
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+ StringBuilder str = new StringBuilder("startElement: ").append(namespaceURI).append(", ").append(namespaceURI).append(", ").append(qName).append(" : ");
+ int n = atts.getLength();
+ for (int i = 0; i < n; i++) {
+ str.append(", ").append(atts.getQName(i)).append(" : ").append(atts.getValue(i));
+ }
+
+ try {
+ bWriter.write(str.toString(), 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
+ String str = "endElement: " + namespaceURI + ", " + namespaceURI + ", " + qName;
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+
+ }
+
+ public void characters(char ch[], int start, int length) throws SAXException {
+ String str = new String(ch, start, length);
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void ignorableWhitespace(char ch[], int start, int length) throws SAXException {
+ String str = "ignorableWhitespace";
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void processingInstruction(String target, String data) throws SAXException {
+ String str = "processingInstruction: " + target + ", " + target;
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+
+ public void skippedEntity(String name) throws SAXException {
+ String str = "skippedEntity: " + name;
+ try {
+ bWriter.write(str, 0, str.length());
+ bWriter.newLine();
+ } catch (IOException e) {
+ System.out.println("bWriter error");
+ }
+ }
+ }
+
+ private static class WrapperException extends RuntimeException {
+ public WrapperException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ private XMLInputFactory ifac;
+ private XMLOutputFactory ofac;
+ private TransformerFactory tfac;
+ private DocumentBuilder db;
+ private byte[] xml;
+ private byte[] template;
+ private Document xmlDoc;
+
+}
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/ptests/TransformerFactoryTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -23,26 +23,79 @@
package javax.xml.transform.ptests;
import java.io.*;
-import java.io.FileOutputStream;
+
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
+
import static javax.xml.transform.ptests.TransformerTestConst.GOLDEN_DIR;
import static javax.xml.transform.ptests.TransformerTestConst.XML_DIR;
+
import javax.xml.transform.stream.*;
+
+import jaxp.library.JAXPDataProvider;
import jaxp.library.JAXPFileBaseTest;
import static jaxp.library.JAXPTestUtilities.USER_DIR;
import static jaxp.library.JAXPTestUtilities.compareWithGold;
+import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.w3c.dom.*;
/**
* Class containing the test cases for TransformerFactory API's
- * getAssociatedStyleSheet method.
+ * getAssociatedStyleSheet method and TransformerFactory.newInstance(factoryClassName , classLoader).
*/
public class TransformerFactoryTest extends JAXPFileBaseTest {
/**
+ * TransformerFactory implementation class name.
+ */
+ private static final String TRANSFORMER_FACTORY_CLASSNAME = "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl";
+
+ /**
+ * Provide valid TransformerFactory instantiation parameters.
+ *
+ * @return a data provider contains TransformerFactory instantiation parameters.
+ */
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { TRANSFORMER_FACTORY_CLASSNAME, null }, { TRANSFORMER_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /**
+ * Test for TransformerFactory.newInstance(java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
+ * points to correct implementation of
+ * javax.xml.transform.TransformerFactory , should return newInstance of
+ * TransformerFactory
+ *
+ * @param factoryClassName
+ * @param classLoader
+ * @throws TransformerConfigurationException
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String factoryClassName, ClassLoader classLoader) throws TransformerConfigurationException {
+ TransformerFactory tf = TransformerFactory.newInstance(factoryClassName, classLoader);
+ Transformer transformer = tf.newTransformer();
+ assertNotNull(transformer);
+ }
+
+ /**
+ * Test for TransformerFactory.newInstance(java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName is
+ * null , should throw TransformerFactoryConfigurationError
+ *
+ * @param factoryClassName
+ * @param classLoader
+ */
+ @Test(expectedExceptions = TransformerFactoryConfigurationError.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceNeg(String factoryClassName, ClassLoader classLoader) {
+ TransformerFactory.newInstance(factoryClassName, classLoader);
+ }
+
+ /**
* This test case checks for the getAssociatedStylesheet method
* of TransformerFactory.
* The style sheet returned is then copied to an tfactory01.out
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/xmlfiles/dataentry.xsl Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+ <xsl:template match="dataentry">
+ <table cellspacing="0" cellpadding="0" width="85%" align="center"
+class="color1" border="0">
+ <xsl:apply-templates/>
+ </table>
+
+ </xsl:template>
+ <xsl:template match="list">
+ <xsl:value-of select="self::node()[@multi='false']"/>
+
+ <!--
+ <xsl:if test="self::node()[@multi='false']">
+ <xsl:if test="self::node()">
+ FALSE<br/>
+ </xsl:if>
+ -->
+ </xsl:template>
+</xsl:stylesheet>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/transform/xmlfiles/test.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,8 @@
+<appcapp>
+<dataentry>
+<list multi="false">
+ <name>TypeOfLifeApp</name>
+</list>
+</dataentry>
+</appcapp>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+
+import jaxp.library.JAXPDataProvider;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.SAXParseException;
+
+/*
+ * @summary Class containing the test cases for SchemaFactory
+ */
+@Test(singleThreaded = true)
+public class SchemaFactoryTest {
+
+ @BeforeClass
+ public void setup() throws SAXException, IOException, ParserConfigurationException {
+ sf = newSchemaFactory();
+
+ assertNotNull(sf);
+
+ xsd1 = Files.readAllBytes(Paths.get(XML_DIR + "test.xsd"));
+ xsd2 = Files.readAllBytes(Paths.get(XML_DIR + "test1.xsd"));
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ xsdDoc1 = db.parse(newInputStream(xsd1));
+ xsdDoc2 = db.parse(newInputStream(xsd2));
+
+ xml = Files.readAllBytes(Paths.get(XML_DIR + "test.xml"));
+ }
+
+
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { W3C_XML_SCHEMA_NS_URI, SCHEMA_FACTORY_CLASSNAME, null },
+ { W3C_XML_SCHEMA_NS_URI, SCHEMA_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /*
+ * test for SchemaFactory.newInstance(java.lang.String schemaLanguage,
+ * java.lang.String factoryClassName, java.lang.ClassLoader classLoader)
+ * factoryClassName points to correct implementation of
+ * javax.xml.validation.SchemaFactory , should return newInstance of
+ * SchemaFactory
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader) throws SAXException {
+ SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI, SCHEMA_FACTORY_CLASSNAME, null);
+ Schema schema = sf.newSchema();
+ assertNotNull(schema);
+ }
+
+ /*
+ * test for SchemaFactory.newInstance(java.lang.String schemaLanguage,
+ * java.lang.String factoryClassName, java.lang.ClassLoader classLoader)
+ * factoryClassName is null , should throw IllegalArgumentException
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceWithNullFactoryClassName(String factoryClassName, ClassLoader classLoader) {
+
+ SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI, factoryClassName, classLoader);
+ }
+
+ /*
+ * test for SchemaFactory.newInstance(java.lang.String schemaLanguage,
+ * java.lang.String factoryClassName, java.lang.ClassLoader classLoader)
+ * schemaLanguage is null , should throw NPE
+ */
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNewInstanceWithNullSchemaLanguage() {
+ SchemaFactory.newInstance(null, SCHEMA_FACTORY_CLASSNAME, this.getClass().getClassLoader());
+ }
+
+ /*
+ * test for SchemaFactory.newInstance(java.lang.String schemaLanguage,
+ * java.lang.String factoryClassName, java.lang.ClassLoader classLoader)
+ * schemaLanguage is empty , should throw IllegalArgumentException
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testNewInstanceWithEmptySchemaLanguage() {
+ SchemaFactory.newInstance("", SCHEMA_FACTORY_CLASSNAME, this.getClass().getClassLoader());
+ }
+
+
+ @Test(expectedExceptions = SAXParseException.class)
+ public void testNewSchemaDefault() throws SAXException, IOException {
+ validate(sf.newSchema());
+ }
+
+ @Test
+ public void testNewSchemaWithFile() throws SAXException, IOException {
+ validate(sf.newSchema(new File(XML_DIR + "test.xsd")));
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNewSchemaWithNullFile() throws SAXException {
+ sf.newSchema((File) null);
+ }
+
+ @DataProvider(name = "valid-source")
+ public Object[][] getValidSource() {
+ return new Object[][] {
+ { streamSource(xsd1) },
+ { saxSource(xsd1) },
+ { domSource(xsdDoc1) } };
+
+ }
+
+ @Test(dataProvider = "valid-source")
+ public void testNewSchemaWithValidSource(Source schema) throws SAXException, IOException {
+ validate(sf.newSchema(schema));
+ }
+
+ @DataProvider(name = "invalid-source")
+ public Object[][] getInvalidSource() {
+ return new Object[][] {
+ { nullStreamSource() },
+ { nullSaxSource() } };
+ }
+
+ @Test(dataProvider = "invalid-source", expectedExceptions = SAXParseException.class)
+ public void testNewSchemaWithInvalidSource(Source schema) throws SAXException {
+ sf.newSchema(schema);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNewSchemaWithNullSource() throws SAXException {
+ sf.newSchema((Source)null);
+ }
+
+ @DataProvider(name = "valid-sources")
+ public Object[][] getValidSources() {
+ return new Object[][] {
+ { streamSource(xsd1), streamSource(xsd2) },
+ { saxSource(xsd1), saxSource(xsd2) },
+ { domSource(xsdDoc1), domSource(xsdDoc2) } };
+
+ }
+
+ @Test(dataProvider = "valid-sources")
+ public void testNewSchemaWithValidSourceArray(Source schema1, Source schema2) throws SAXException, IOException {
+ validate(sf.newSchema(new Source[] { schema1, schema2 }));
+ }
+
+ @DataProvider(name = "invalid-sources")
+ public Object[][] getInvalidSources() {
+ return new Object[][] {
+ { streamSource(xsd1), nullStreamSource() },
+ { nullStreamSource(), nullStreamSource() },
+ { saxSource(xsd1), nullSaxSource() },
+ { nullSaxSource(), nullSaxSource() } };
+ }
+
+ @Test(dataProvider = "invalid-sources", expectedExceptions = SAXParseException.class)
+ public void testNewSchemaWithInvalidSourceArray(Source schema1, Source schema2) throws SAXException {
+ sf.newSchema(new Source[] { schema1, schema2 });
+ }
+
+ @DataProvider(name = "null-sources")
+ public Object[][] getNullSources() {
+ return new Object[][] {
+ { new Source[] { domSource(xsdDoc1), null } },
+ { new Source[] { null, null } },
+ { null } };
+
+ }
+
+ @Test(dataProvider = "null-sources", expectedExceptions = NullPointerException.class)
+ public void testNewSchemaWithNullSourceArray(Source[] schemas) throws SAXException {
+ sf.newSchema(schemas);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNewSchemaWithNullUrl() throws SAXException {
+ sf.newSchema((URL) null);
+ }
+
+
+ @Test
+ public void testErrorHandler() {
+ SchemaFactory sf = newSchemaFactory();
+ assertNull(sf.getErrorHandler(), "When SchemaFactory is created, initially ErrorHandler should not be set.");
+
+ ErrorHandler handler = new MyErrorHandler();
+ sf.setErrorHandler(handler);
+ assertSame(sf.getErrorHandler(), handler);
+
+ sf.setErrorHandler(null);
+ assertNull(sf.getErrorHandler());
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testGetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ sf.getProperty(UNRECOGNIZED_NAME);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testSetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ sf.setProperty(UNRECOGNIZED_NAME, "test");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ assertNotNull(sf);
+ sf.getProperty(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ assertNotNull(sf);
+ sf.setProperty(null, "test");
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testGetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ sf.getFeature(UNRECOGNIZED_NAME);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testSetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ sf.setFeature(UNRECOGNIZED_NAME, true);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ assertNotNull(sf);
+ sf.getFeature(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ SchemaFactory sf = newSchemaFactory();
+ assertNotNull(sf);
+ sf.setFeature(null, true);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testInvalidSchemaLanguage() {
+ final String INVALID_SCHEMA_LANGUAGE = "http://relaxng.org/ns/structure/1.0";
+ SchemaFactory.newInstance(INVALID_SCHEMA_LANGUAGE);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNullSchemaLanguage() {
+ SchemaFactory.newInstance(null);
+ }
+
+ private void validate(Schema schema) throws SAXException, IOException {
+ schema.newValidator().validate(new StreamSource(new ByteArrayInputStream(xml)));
+ }
+ private InputStream newInputStream(byte[] xsd) {
+ return new ByteArrayInputStream(xsd);
+ }
+
+ private Source streamSource(byte[] xsd) {
+ return new StreamSource(newInputStream(xsd));
+ }
+
+ private Source nullStreamSource() {
+ return new StreamSource((InputStream) null);
+ }
+
+ private Source saxSource(byte[] xsd) {
+ return new SAXSource(new InputSource(newInputStream(xsd)));
+ }
+
+ private Source nullSaxSource() {
+ return new SAXSource(new InputSource((InputStream) null));
+ }
+
+ private Source domSource(Document xsdDoc) {
+ return new DOMSource(xsdDoc);
+ }
+
+ private SchemaFactory newSchemaFactory() {
+ return SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ }
+
+ private static final String UNRECOGNIZED_NAME = "http://xml.org/sax/features/namespace-prefixes";
+
+ private static final String SCHEMA_FACTORY_CLASSNAME = "com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory";
+
+ private SchemaFactory sf;
+ private byte[] xsd1;
+ private byte[] xsd2;
+ private Document xsdDoc1;
+ private Document xsdDoc2;
+ private byte[] xml;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/TypeInfoProviderTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR;
+import static jaxp.library.JAXPTestUtilities.filenameToURL;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.TypeInfoProvider;
+import javax.xml.validation.ValidatorHandler;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+
+/*
+ * @summary test ValidatorHandler.getTypeInfoProvider()
+ */
+public class TypeInfoProviderTest extends JAXPFileBaseTest {
+
+ private ValidatorHandler validatorHandler;
+
+ @Test
+ public void test() throws SAXException, ParserConfigurationException, IOException {
+
+ SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI);
+ Schema schema = sf.newSchema(new File(XML_DIR + "shiporder11.xsd"));
+ validatorHandler = schema.newValidatorHandler();
+ MyDefaultHandler myDefaultHandler = new MyDefaultHandler();
+ validatorHandler.setContentHandler(myDefaultHandler);
+
+ InputSource is = new InputSource(filenameToURL(XML_DIR + "shiporder11.xml"));
+
+ SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ parserFactory.setNamespaceAware(true);
+ XMLReader xmlReader = parserFactory.newSAXParser().getXMLReader();
+ xmlReader.setContentHandler(validatorHandler);
+ xmlReader.parse(is);
+
+ }
+
+ private class MyDefaultHandler extends DefaultHandler {
+
+ public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+ TypeInfoProvider typeInfoProvider = validatorHandler.getTypeInfoProvider();
+ int index = atts.getIndex("orderid");
+ if (index != -1) {
+ System.out.println(" Index " + index);
+ System.out.println(" ElementType " + typeInfoProvider.getElementTypeInfo().getTypeName());
+ assertEquals(typeInfoProvider.getAttributeTypeInfo(index).getTypeName(), "string");
+ assertTrue(typeInfoProvider.isSpecified(index));
+ assertFalse(typeInfoProvider.isIdAttribute(index));
+ }
+
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorHandlerTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.ValidatorHandler;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/*
+ * @summary Class containing the test cases for ValidatorHandler API
+ */
+public class ValidatorHandlerTest {
+ @BeforeClass
+ public void setup() throws SAXException {
+ schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI).newSchema(new File(XML_DIR + "test.xsd"));
+
+ assertNotNull(schema);
+ }
+
+ @Test
+ public void testErrorHandler() {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNull(validatorHandler.getErrorHandler(), "When ValidatorHandler is created, initially ErrorHandler should not be set.");
+
+ ErrorHandler handler = new MyErrorHandler();
+ validatorHandler.setErrorHandler(handler);
+ assertSame(validatorHandler.getErrorHandler(), handler);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testGetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ validatorHandler.getProperty(FEATURE_NAME);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testSetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ validatorHandler.setProperty(FEATURE_NAME, "test");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNotNull(validatorHandler);
+ validatorHandler.getProperty(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNotNull(validatorHandler);
+ validatorHandler.setProperty(null, "test");
+ }
+
+ public void testFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertFalse(validatorHandler.getFeature(FEATURE_NAME), "The feature should be false by default.");
+
+ validatorHandler.setFeature(FEATURE_NAME, true);
+ assertTrue(validatorHandler.getFeature(FEATURE_NAME), "The feature should be false by default.");
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNotNull(validatorHandler);
+ validatorHandler.getFeature(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNotNull(validatorHandler);
+ validatorHandler.setFeature(null, true);
+ }
+
+ @Test
+ public void testContentHandler() {
+ ValidatorHandler validatorHandler = getValidatorHandler();
+ assertNull(validatorHandler.getContentHandler(), "When ValidatorHandler is created, initially ContentHandler should not be set.");
+
+ ContentHandler handler = new DefaultHandler();
+ validatorHandler.setContentHandler(handler);
+ assertSame(validatorHandler.getContentHandler(), handler);
+
+ validatorHandler.setContentHandler(null);
+ assertNull(validatorHandler.getContentHandler());
+
+ }
+
+ private ValidatorHandler getValidatorHandler() {
+ return schema.newValidatorHandler();
+ }
+
+ private static final String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes";
+
+ private Schema schema;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
+import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR;
+import static jaxp.library.JAXPTestUtilities.filenameToURL;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertSame;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.sax.SAXResult;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/*
+ * @summary Class containing the test cases for Validator API
+ */
+public class ValidatorTest extends JAXPFileBaseTest {
+
+ @BeforeClass
+ public void setup() throws SAXException, IOException, ParserConfigurationException {
+ schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI).newSchema(new File(XML_DIR + "test.xsd"));
+
+ assertNotNull(schema);
+
+ xmlFileUri = filenameToURL(XML_DIR + "test.xml");
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ xmlDoc = dbf.newDocumentBuilder().parse(xmlFileUri);
+ }
+
+ @Test
+ public void testValidateStreamSource() throws SAXException, IOException {
+ Validator validator = getValidator();
+ validator.setErrorHandler(new MyErrorHandler());
+ validator.validate(getStreamSource());
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testValidateNullSource() throws SAXException, IOException {
+ Validator validator = getValidator();
+ assertNotNull(validator);
+ validator.validate(null);
+ }
+
+ @Test
+ public void testErrorHandler() {
+ Validator validator = getValidator();
+ assertNull(validator.getErrorHandler(), "When Validator is created, initially ErrorHandler should not be set.");
+
+ ErrorHandler mh = new MyErrorHandler();
+ validator.setErrorHandler(mh);
+ assertSame(validator.getErrorHandler(), mh);
+
+ }
+
+ @DataProvider(name = "source-result")
+ public Object[][] getSourceAndResult() {
+ return new Object[][] {
+ { getStreamSource(), null },
+ { getSAXSource(), getSAXResult() },
+ { getDOMSource(), getDOMResult() },
+ { getSAXSource(), null },
+ { getDOMSource(), null } };
+ }
+
+ @Test(dataProvider = "source-result")
+ public void testValidateWithResult(Source source, Result result) throws SAXException, IOException {
+ Validator validator = getValidator();
+ validator.validate(source, result);
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testGetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ validator.getProperty(UNRECOGNIZED_NAME);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testSetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ validator.setProperty(UNRECOGNIZED_NAME, "test");
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ assertNotNull(validator);
+ validator.getProperty(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ assertNotNull(validator);
+ validator.setProperty(null, "test");
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testGetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ validator.getFeature(UNRECOGNIZED_NAME);
+
+ }
+
+ @Test(expectedExceptions = SAXNotRecognizedException.class)
+ public void testSetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ validator.setFeature(UNRECOGNIZED_NAME, true);
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testGetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ assertNotNull(validator);
+ validator.getFeature(null);
+
+ }
+
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testSetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException {
+ Validator validator = getValidator();
+ assertNotNull(validator);
+ validator.setFeature(null, true);
+ }
+
+ private Validator getValidator() {
+ return schema.newValidator();
+ }
+
+ private Source getStreamSource() {
+ return new StreamSource(xmlFileUri);
+ }
+
+ private Source getSAXSource() {
+ return new SAXSource(new InputSource(xmlFileUri));
+ }
+
+ private Result getSAXResult() {
+ SAXResult saxResult = new SAXResult();
+ saxResult.setHandler(new DefaultHandler());
+ return saxResult;
+ }
+
+ private Source getDOMSource() {
+ return new DOMSource(xmlDoc);
+ }
+
+ private Result getDOMResult() {
+ return new DOMResult();
+ }
+
+ private static final String UNRECOGNIZED_NAME = "http://xml.org/sax/features/namespace-prefixes";
+ private String xmlFileUri;
+ private Schema schema;
+ private Document xmlDoc;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<shiporder orderid="889923"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:noNamespaceSchemaLocation="shiporder.xsd">
+<orderperson>John Smith</orderperson>
+<shipto>
+<name>Ola Nordmann</name>
+<address>Langgt 23</address>
+<city>4000 Stavanger</city>
+<country>Norway</country>
+</shipto>
+<item>
+<title>Empire Burlesque</title>
+<note>Special Edition</note>
+<quantity>1</quantity>
+<price>10.90</price>
+</item>
+<item>
+<title>Hide your heart</title>
+<quantity>1</quantity>
+<price>9.90</price>
+</item>
+</shiporder>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xsd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<!-- definition of simple elements -->
+<xs:element name="orderperson" type="xs:string"/>
+<xs:element name="name" type="xs:string"/>
+<xs:element name="address" type="xs:string"/>
+<xs:element name="city" type="xs:string"/>
+<xs:element name="country" type="xs:string"/>
+<xs:element name="title" type="xs:string"/>
+<xs:element name="note" type="xs:string"/>
+<xs:element name="quantity" type="xs:positiveInteger"/>
+<xs:element name="price" type="xs:decimal"/>
+
+<!-- definition of attributes -->
+<xs:attribute name="orderid" type="xs:string"/>
+
+<!-- definition of complex elements -->
+<xs:element name="shipto">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="name"/>
+<xs:element ref="address"/>
+<xs:element ref="city"/>
+<xs:element ref="country"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+<xs:element name="item">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="title"/>
+<xs:element ref="note" minOccurs="0"/>
+<xs:element ref="quantity"/>
+<xs:element ref="price"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+
+<xs:element name="shiporder">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="orderperson"/>
+<xs:element ref="shipto"/>
+<xs:element ref="item" maxOccurs="unbounded"/>
+</xs:sequence>
+<xs:attribute ref="orderid" use="required"/>
+</xs:complexType>
+</xs:element>
+
+</xs:schema>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<shiporder orderid="889923"
+xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+xsi:noNamespaceSchemaLocation="shiporder.xsd">
+<orderperson>John Smith</orderperson>
+<shipto>
+<name>Ola Nordmann</name>
+<address>Langgt 23</address>
+<city>4000 Stavanger</city>
+<country>Norway</country>
+</shipto>
+<item>
+<title>Empire Burlesque</title>
+<note>Special Edition</note>
+<quantity>1</quantity>
+<price>10.90</price>
+</item>
+<item>
+<title>Hide your heart</title>
+<quantity>1</quantity>
+<price>9.90</price>
+</item>
+</shiporder>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xsd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+<!-- definition of simple elements -->
+<xs:element name="orderperson" type="xs:string"/>
+<xs:element name="name" type="xs:string"/>
+<xs:element name="address" type="xs:string"/>
+<xs:element name="city" type="xs:string"/>
+<xs:element name="country" type="xs:string"/>
+<xs:element name="title" type="xs:string"/>
+<xs:element name="note" type="xs:string"/>
+<xs:element name="quantity" type="xs:positiveInteger"/>
+<xs:element name="price" type="xs:decimal"/>
+
+<!-- definition of attributes -->
+<xs:attribute name="orderid" type="xs:string"/>
+
+<!-- definition of complex elements -->
+<xs:element name="shipto">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="name"/>
+<xs:element ref="address"/>
+<xs:element ref="city"/>
+<xs:element ref="country"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+<xs:element name="item">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="title"/>
+<xs:element ref="note" minOccurs="0"/>
+<xs:element ref="quantity"/>
+<xs:element ref="price"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+
+<xs:element name="shiporder">
+<xs:complexType>
+<xs:sequence>
+<xs:element ref="orderperson"/>
+<xs:element ref="shipto"/>
+<xs:element ref="item" maxOccurs="unbounded"/>
+</xs:sequence>
+<xs:attribute ref="orderid" use="required"/>
+</xs:complexType>
+</xs:element>
+
+</xs:schema>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+ <contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd">
+<name> John </name>
+<phone>444-121-3434</phone>
+</contact>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xsd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+<xs:element name="contact">
+<xs:complexType>
+<xs:sequence>
+ <xs:element name="name" type="xs:string"/>
+ <xs:element name="phone" type="xs:string"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test1.xsd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
+<xs:element name="address">
+<xs:complexType>
+<xs:sequence>
+ <xs:element name="street" type="xs:string"/>
+ <xs:element name="city" type="xs:string"/>
+</xs:sequence>
+</xs:complexType>
+</xs:element>
+</xs:schema>
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/xpath/ptests/XPathFactoryTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -24,10 +24,16 @@
package javax.xml.xpath.ptests;
import static javax.xml.xpath.XPathConstants.DOM_OBJECT_MODEL;
+
+import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;
+
+import jaxp.library.JAXPDataProvider;
import jaxp.library.JAXPBaseTest;
-import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.Assert.assertNotNull;
+
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/**
@@ -45,6 +51,78 @@
private static final String INVALID_URL = "http://java.sun.com/jaxp/xpath/dom1";
/**
+ * XPathFactory implementation class name.
+ */
+ private static final String XPATH_FACTORY_CLASSNAME = "com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl";
+
+
+ /**
+ * Provide valid XPathFactory instantiation parameters.
+ *
+ * @return a data provider contains XPathFactory instantiation parameters.
+ */
+ @DataProvider(name = "parameters")
+ public Object[][] getValidateParameters() {
+ return new Object[][] { { VALID_URL, XPATH_FACTORY_CLASSNAME, null }, { VALID_URL, XPATH_FACTORY_CLASSNAME, this.getClass().getClassLoader() } };
+ }
+
+ /**
+ * Test for XPathFactory.newInstance(java.lang.String uri, java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) factoryClassName
+ * points to correct implementation of javax.xml.xpath.XPathFactory , should
+ * return newInstance of XPathFactory
+ *
+ * @param uri
+ * @param factoryClassName
+ * @param classLoader
+ * @throws XPathFactoryConfigurationException
+ */
+ @Test(dataProvider = "parameters")
+ public void testNewInstance(String uri, String factoryClassName, ClassLoader classLoader) throws XPathFactoryConfigurationException {
+ XPathFactory xpf = XPathFactory.newInstance(uri, factoryClassName, classLoader);
+ XPath xpath = xpf.newXPath();
+ assertNotNull(xpath);
+ }
+
+ /**
+ * Test for XPathFactory.newInstance(java.lang.String uri, java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader)
+ *
+ * @param factoryClassName
+ * @param classLoader
+ * @throws XPathFactoryConfigurationException
+ * is expected when factoryClassName is null
+ */
+ @Test(expectedExceptions = XPathFactoryConfigurationException.class, dataProvider = "new-instance-neg", dataProviderClass = JAXPDataProvider.class)
+ public void testNewInstanceWithNullFactoryClassName(String factoryClassName, ClassLoader classLoader) throws XPathFactoryConfigurationException {
+ XPathFactory.newInstance(VALID_URL, factoryClassName, classLoader);
+ }
+
+ /**
+ * Test for XPathFactory.newInstance(java.lang.String uri, java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader) uri is null , should
+ * throw NPE
+ *
+ * @throws XPathFactoryConfigurationException
+ */
+ @Test(expectedExceptions = NullPointerException.class)
+ public void testNewInstanceWithNullUri() throws XPathFactoryConfigurationException {
+ XPathFactory.newInstance(null, XPATH_FACTORY_CLASSNAME, this.getClass().getClassLoader());
+ }
+
+ /**
+ * Test for XPathFactory.newInstance(java.lang.String uri, java.lang.String
+ * factoryClassName, java.lang.ClassLoader classLoader)
+ *
+ * @throws IllegalArgumentException
+ * is expected when uri is empty
+ */
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void testNewInstanceWithEmptyUri() throws XPathFactoryConfigurationException {
+ XPathFactory.newInstance("", XPATH_FACTORY_CLASSNAME, this.getClass().getClassLoader());
+ }
+
+ /**
* Test for constructor - XPathFactory.newInstance().
*/
@Test
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4511326.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.gaptest;
+
+import java.io.StringReader;
+
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.Test;
+
+/*
+ * @bug 4511326
+ * @summary In forwards-compatible mode the attribute isn't ignored
+ */
+
+public class Bug4511326 extends JAXPBaseTest {
+
+ private static final String XSL = "<xsl:stylesheet version='2.0' "
+ + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"
+ + "<xsl:template a='1' match='/'>"
+ + "<H2><xsl:value-of select='//author'/></H2>"
+ + "<H1><xsl:value-of select='//title'/></H1>"
+ + "</xsl:template>"
+ + "</xsl:stylesheet>";
+
+
+ @Test
+ public void ignoreAttTest() throws TransformerConfigurationException {
+ /* Create a TransformFactory instance */
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+ /* Create and init a StreamSource instance */
+ StreamSource source = new StreamSource(new StringReader(XSL));
+
+ transformerFactory.newTransformer(source);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4512806.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.gaptest;
+
+import static javax.xml.transform.OutputKeys.ENCODING;
+import static javax.xml.transform.OutputKeys.INDENT;
+import static org.testng.Assert.assertEquals;
+
+import java.io.StringReader;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.Test;
+
+/*
+ * @bug 4512806
+ * @summary test transformer.setOutputProperties(null)
+ */
+public class Bug4512806 extends JAXPBaseTest {
+
+ @Test
+ public void testProperty() throws TransformerConfigurationException {
+ /* Create a transform factory instance */
+ TransformerFactory tfactory = TransformerFactory.newInstance();
+
+ /* Create a StreamSource instance */
+ StreamSource streamSource = new StreamSource(new StringReader(xslData));
+
+ transformer = tfactory.newTransformer(streamSource);
+ transformer.setOutputProperty(INDENT, "no");
+ transformer.setOutputProperty(ENCODING, "UTF-16");
+
+ assertEquals(printPropertyValue(INDENT), "indent=no");
+ assertEquals(printPropertyValue(ENCODING), "encoding=UTF-16");
+
+ transformer.setOutputProperties(null);
+
+ assertEquals(printPropertyValue(INDENT), "indent=yes");
+ assertEquals(printPropertyValue(ENCODING), "encoding=UTF-8");
+
+ }
+
+ private String printPropertyValue(String name) {
+ return name + "=" + transformer.getOutputProperty(name);
+ }
+
+ private Transformer transformer;
+
+ private static final String xslData = "<?xml version='1.0'?>"
+ + "<xsl:stylesheet"
+ + " version='1.0'"
+ + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'"
+ + ">\n"
+ + " <xsl:output method='xml' indent='yes'"
+ + " encoding='UTF-8'/>\n"
+ + " <xsl:template match='/'>\n"
+ + " Hello World! \n"
+ + " </xsl:template>\n"
+ + "</xsl:stylesheet>";
+
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515047.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.gaptest;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.Test;
+
+/*
+ * @bug 4515047
+ * @summary test transform an empty dom source
+ */
+
+public class Bug4515047 extends JAXPBaseTest {
+
+ @Test
+ public void testCreateTxDoc() throws TransformerException, ParserConfigurationException {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+
+ StreamResult result = new StreamResult(System.out);
+ DOMSource source = new DOMSource();
+
+ /* This should not throw an Illegal Argument Exception */
+ //Test empty DOMSource
+ transformer.transform(source, result);
+
+ //Test DOMSource having only an empty node
+ source.setNode(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
+ transformer.transform(source, result);
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515660.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.gaptest;
+
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+
+import jaxp.library.JAXPBaseTest;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+/*
+ * @bug 4515660
+ * @summary verify property org.xml.sax.driver is used by SAXTransformerFactory
+ */
+@Test(singleThreaded = true)
+public class Bug4515660 extends JAXPBaseTest {
+
+ @BeforeClass
+ public void setSaxDrier() {
+ setSystemProperty("org.xml.sax.driver", ReaderStub.class.getName());
+ }
+
+ @AfterClass
+ public void clearSaxDrier() {
+ setSystemProperty("org.xml.sax.driver", null);
+ }
+
+ @Test
+ public void testTransformer() throws TransformerException {
+ String xml = "<?xml version='1.0'?><root/>";
+ ReaderStub.used = false;
+
+ TransformerFactory transFactory = TransformerFactory.newInstance();
+ Transformer transformer = transFactory.newTransformer();
+ InputSource in = new InputSource(new StringReader(xml));
+ SAXSource source = new SAXSource(in);
+ StreamResult result = new StreamResult(new StringWriter());
+
+ transformer.transform(source, result);
+
+ assertTrue(ReaderStub.used);
+
+ }
+
+ @Test
+ public void testSAXTransformerFactory() throws TransformerConfigurationException {
+ final String xsl = "<?xml version='1.0'?>\n" + "<xsl:stylesheet" + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" + " version='1.0'>\n"
+ + " <xsl:template match='/'>Hello World!</xsl:template>\n" + "</xsl:stylesheet>\n";
+
+ ReaderStub.used = false;
+
+ TransformerFactory transFactory = TransformerFactory.newInstance();
+ assertTrue(transFactory.getFeature(SAXTransformerFactory.FEATURE));
+
+ InputSource in = new InputSource(new StringReader(xsl));
+ SAXSource source = new SAXSource(in);
+
+ transFactory.newTransformer(source);
+ assertTrue(ReaderStub.used);
+
+ }
+
+ public static class ReaderStub extends XMLFilterImpl {
+ static boolean used = false;
+
+ public ReaderStub() throws ParserConfigurationException, SAXException {
+ super();
+ super.setParent(SAXParserFactory.newInstance().newSAXParser().getXMLReader());
+ used = true;
+ }
+
+ public void parse(InputSource input) throws SAXException, IOException {
+ used = true;
+ super.parse(input);
+ }
+
+ public void parse(String systemId) throws SAXException, IOException {
+ used = true;
+ super.parse(systemId);
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4693341.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test.gaptest;
+
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import static jaxp.library.JAXPTestUtilities.USER_DIR;
+import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold;
+import static org.testng.Assert.assertTrue;
+import static test.gaptest.GapTestConst.GOLDEN_DIR;
+import static test.gaptest.GapTestConst.XML_DIR;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+
+/*
+ * @bug 4693341
+ * @summary test transforming to stream with external dtd
+ */
+
+public class Bug4693341 extends JAXPFileBaseTest {
+
+ @Test
+ public void test() throws TransformerException, ParserConfigurationException, SAXException, IOException {
+
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+
+ String out = USER_DIR + File.separator + "Bug4693341.out";
+ StreamResult result = new StreamResult(new File(out));
+
+ String in = XML_DIR + "Bug4693341.xml";
+ String golden = GOLDEN_DIR + "Bug4693341.xml";
+ File file = new File(in);
+ StreamSource source = new StreamSource(file);
+ System.out.println(source.getSystemId());
+
+ Files.copy(Paths.get(XML_DIR + "Bug4693341.dtd"),
+ Paths.get(USER_DIR + File.separator + "Bug4693341.dtd"), REPLACE_EXISTING);
+
+ transformer.transform(source, result);
+
+ assertTrue(compareDocumentWithGold(golden, out));
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4848653.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.gaptest;
+
+import static jaxp.library.JAXPTestUtilities.filenameToURL;
+import static test.gaptest.GapTestConst.XML_DIR;
+
+import java.io.IOException;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/*
+ * @bug 4848653
+ * @summary Verify JAXP schemaLanguage property is ignored if setValidating(false)
+ */
+
+public class Bug4848653 extends JAXPFileBaseTest {
+
+ @Test
+ public void test() throws IOException, SAXException, ParserConfigurationException {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+ SAXParser parser = factory.newSAXParser();
+ parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", XMLConstants.W3C_XML_SCHEMA_NS_URI);
+
+ String filename = XML_DIR + "Bug4848653.xml";
+ InputSource is = new InputSource(filenameToURL(filename));
+ XMLReader xmlReader = parser.getXMLReader();
+ xmlReader.setErrorHandler(new MyErrorHandler());
+ xmlReader.parse(is);
+ }
+
+ class MyErrorHandler implements ErrorHandler {
+ public void error(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+
+ public void warning(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4858685.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.gaptest;
+
+import static jaxp.library.JAXPTestUtilities.filenameToURL;
+import static org.testng.Assert.assertEquals;
+import static test.gaptest.GapTestConst.GOLDEN_DIR;
+import static test.gaptest.GapTestConst.XML_DIR;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamSource;
+
+import jaxp.library.JAXPFileBaseTest;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/*
+ * @bug 4858685 4894410
+ * @summary test transforming text node
+ */
+
+public class Bug4858685 extends JAXPFileBaseTest {
+ @Test
+ public void test() throws TransformerException, IOException {
+ String uri = XML_DIR + "certificate.xml";
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+
+ Transformer transformer = transformerFactory.newTransformer();
+
+ // use URI as a StreamSource
+ StreamSource streamSource = new StreamSource(filenameToURL(uri));
+
+ DOMResult domResult = new DOMResult();
+
+ // StreamSource -> DOMResult
+ transformer.transform(streamSource, domResult);
+
+ // dump DOM in a human readable form
+ String gotString = DOMDump.dumpDom(domResult.getNode());
+
+ String goldenString = new String(Files.readAllBytes(Paths.get(GOLDEN_DIR + "Bug4858685.txt")));
+
+ assertEquals(gotString, goldenString);
+
+ }
+
+ /**
+ * DOMDump: dump a DOM to a String in human readable form. method dumpDOM()
+ * is static for easy calling:
+ */
+ private static class DOMDump {
+
+ /**
+ * the maximum level to indent with blanks
+ */
+ private static final int BLANKS_LEN = 64;
+
+ /**
+ * each level of the tree will be indented with blanks for readability
+ */
+ private static final String BLANKS = " ";
+
+ /**
+ * dumpDOM will dump the DOM into a String for human readability
+ *
+ * @param domNode
+ * the DOM Node to dump
+ * @return human readabile DOM as a String
+ */
+ public static String dumpDom(Node domNode) {
+ return dumpInternal(domNode, 0);
+ }
+
+ /**
+ * dumpInternal is used internaly to recursively dump DOM Nodes
+ *
+ * @param domNode
+ * to dump
+ * @param indent
+ * level
+ * @return domNode as human readable String
+ */
+ private static String dumpInternal(Node domNode, int indent) {
+
+ String result = "";
+
+ // indent for readability
+ result += indentBlanks(indent);
+ indent += 2;
+
+ // protect against null
+ if (domNode == null) {
+ result = result + "[null]" + "\n";
+ return result;
+ }
+
+ // what to output depends on NodeType
+ short type = domNode.getNodeType();
+ switch (type) {
+ case Node.ATTRIBUTE_NODE: {
+ result += "[attribute] " + domNode.getNodeName() + "=\"" + domNode.getNodeValue() + "\"";
+ break;
+ }
+ case Node.CDATA_SECTION_NODE: {
+ result += "[cdata] " + domNode.getNodeValue();
+ break;
+ }
+ case Node.COMMENT_NODE: {
+ result += "[comment] " + domNode.getNodeValue();
+ break;
+ }
+ case Node.DOCUMENT_FRAGMENT_NODE: {
+ result += "[document fragment]";
+ break;
+ }
+ case Node.DOCUMENT_NODE: {
+ result += "[document]";
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE: {
+ result += "[document type] " + domNode.getNodeName();
+ break;
+ }
+ case Node.ELEMENT_NODE: {
+ result += "[element] " + domNode.getNodeName();
+ // output all attributes for Element
+ if (domNode.hasAttributes()) {
+ NamedNodeMap attributes = domNode.getAttributes();
+ for (int onAttribute = 0; onAttribute < attributes.getLength(); onAttribute++) {
+
+ // seprate each attribute with a space
+ result += " ";
+
+ Node attribute = attributes.item(onAttribute);
+ String namespaceURI = attribute.getNamespaceURI();
+ String prefix = attribute.getPrefix();
+ String localName = attribute.getLocalName();
+ String name = attribute.getNodeName();
+ String value = attribute.getNodeValue();
+
+ // using Namespaces?
+ if (namespaceURI != null) {
+ result += "{" + namespaceURI + "}";
+ }
+ if (prefix != null) {
+ result += prefix + ":";
+ }
+
+ // name="value"
+ result += attribute.getNodeName() + "=\"" + attribute.getNodeValue() + "\"";
+ }
+ }
+
+ break;
+ }
+ case Node.ENTITY_NODE: {
+ result += "[entity] " + domNode.getNodeName();
+ break;
+ }
+ case Node.ENTITY_REFERENCE_NODE: {
+ result += "[entity reference] " + domNode.getNodeName();
+ break;
+ }
+ case Node.NOTATION_NODE: {
+ result += "[notation] " + domNode.getNodeName();
+ break;
+ }
+ case Node.PROCESSING_INSTRUCTION_NODE: {
+ result += "[pi] target=\"" + domNode.getNodeName() + "\" content=\"" + domNode.getNodeValue() + "\"";
+ break;
+ }
+ case Node.TEXT_NODE: {
+ result += "[text] " + domNode.getNodeValue();
+ break;
+ }
+ default: {
+ result += "[unknown]";
+ break;
+ }
+ }
+
+ // humans read in lines
+ result += "\n";
+
+ // process children
+ NodeList children = domNode.getChildNodes();
+ for (int onChild = 0; onChild < children.getLength(); onChild++) {
+ Node child = children.item(onChild);
+ result += dumpInternal(child, indent);
+ }
+
+ // return human readable DOM as String
+ return result;
+ }
+
+ /**
+ * indentBlanks will return a String of indent blanks
+ *
+ * @param indent
+ * level
+ * @return String of blanks
+ */
+ private static String indentBlanks(int indent) {
+ if (indent == 0) {
+ return "";
+ }
+
+ if (indent > BLANKS_LEN) {
+ return BLANKS;
+ }
+
+ return BLANKS.substring(0, indent + 1);
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.dtd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,39 @@
+<!ELEMENT SupplierOrder (OrderId, OrderDate, ShippingAddress, LineItems)>
+
+<!ELEMENT OrderId (#PCDATA)>
+
+<!ELEMENT OrderDate (#PCDATA)>
+
+<!ELEMENT ShippingAddress (FirstName, LastName, Street, City, State, Country, ZipCode, Email, Phone)>
+
+<!ELEMENT FirstName (#PCDATA)>
+
+<!ELEMENT LastName (#PCDATA)>
+
+<!ELEMENT Street (#PCDATA)>
+
+<!ELEMENT City (#PCDATA)>
+
+<!ELEMENT State (#PCDATA)>
+
+<!ELEMENT Country (#PCDATA)>
+
+<!ELEMENT ZipCode (#PCDATA)>
+
+<!ELEMENT Email (#PCDATA)>
+
+<!ELEMENT Phone (#PCDATA)>
+
+<!ELEMENT LineItems (LineItem+)>
+
+<!ELEMENT LineItem EMPTY>
+
+<!ATTLIST LineItem
+ categoryId CDATA #REQUIRED
+ productId CDATA #REQUIRED
+ itemId CDATA #REQUIRED
+ lineNo CDATA #REQUIRED
+ quantity CDATA #REQUIRED
+ unitPrice CDATA #REQUIRED
+>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE SupplierOrder SYSTEM "Bug4693341.dtd" >
+<SupplierOrder>
+<OrderId>10016</OrderId>
+<OrderDate>Wed May 29 12:45:00 PDT 2002</OrderDate>
+<ShippingAddress>
+<FirstName>ABC</FirstName>
+<LastName>XYZ</LastName>
+<Street>1234 Anywhere Street</Street>
+<City>Palo Alto</City>
+<State>California</State>
+<Country>USA</Country>
+<ZipCode>94303</ZipCode>
+<Email>NULL</Email>
+<Phone>NULL</Phone>
+</ShippingAddress>
+<LineItems>
+<LineItem categoryId="BIRDS" itemId="EST-18" lineNo="0" productId="AV-CB-01" quantity="1" unitPrice="193.5"/>
+</LineItems>
+</SupplierOrder>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4848653.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,1 @@
+<a/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/certificate.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<env:Envelope xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/"
+ xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
+ xmlns:ns0="http://headertest.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <env:Body>
+ <ds:X509Certificate xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+MIIDVjCCAxICBD6kKrMwCwYHKoZIzjgEAwUAMIGPMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+FDASBgNVBAcTC1NhbnRhIENsYXJhMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMR4w
+HAYDVQQLExVKYXZhIGFuZCBYTUwgU29mdHdhcmUxHDAaBgNVBAMTE0pXUy1TZWN1cml0eSBDbGll
+bnQwHhcNMDMwNDIxMTczMDI3WhcNMDMwNzIwMTczMDI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV
+BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEfMB0GA1UEChMWU3VuIE1pY3Jvc3lzdGVtcywg
+SW5jLjEeMBwGA1UECxMVSmF2YSBhbmQgWE1MIFNvZnR3YXJlMRwwGgYDVQQDExNKV1MtU2VjdXJp
+dHkgQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E
+AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up
+1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj
+C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZ
+T+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7
+zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAV3R+bUfh+u0yaPBV75umKvFB
+ucv37ETDak889b7k72kZdGoHz3oDmp69tiNDg5r7IvKtjHGbZ6C3Nv0ycNR7Sed1QPOF4nn/tgUl
+j+BvtVW3iiIRgBJ82KP+28QtwPkkxSp7n5HG0v7bE29E/juLduuhKBQTaaCvajuCFxiBrmAwCwYH
+KoZIzjgEAwUAAzEAMC4CFQCCuDNmMKjgY6MV1SmAcCdnhuT6VwIVAJBOiPDnDWp2WlKAERF6nOAf
+vKz9
+ </ds:X509Certificate>
+ </env:Body>
+</env:Envelope>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.dtd Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,39 @@
+<!ELEMENT SupplierOrder (OrderId, OrderDate, ShippingAddress, LineItems)>
+
+<!ELEMENT OrderId (#PCDATA)>
+
+<!ELEMENT OrderDate (#PCDATA)>
+
+<!ELEMENT ShippingAddress (FirstName, LastName, Street, City, State, Country, ZipCode, Email, Phone)>
+
+<!ELEMENT FirstName (#PCDATA)>
+
+<!ELEMENT LastName (#PCDATA)>
+
+<!ELEMENT Street (#PCDATA)>
+
+<!ELEMENT City (#PCDATA)>
+
+<!ELEMENT State (#PCDATA)>
+
+<!ELEMENT Country (#PCDATA)>
+
+<!ELEMENT ZipCode (#PCDATA)>
+
+<!ELEMENT Email (#PCDATA)>
+
+<!ELEMENT Phone (#PCDATA)>
+
+<!ELEMENT LineItems (LineItem+)>
+
+<!ELEMENT LineItem EMPTY>
+
+<!ATTLIST LineItem
+ categoryId CDATA #REQUIRED
+ productId CDATA #REQUIRED
+ itemId CDATA #REQUIRED
+ lineNo CDATA #REQUIRED
+ quantity CDATA #REQUIRED
+ unitPrice CDATA #REQUIRED
+>
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.xml Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE SupplierOrder SYSTEM "Bug4693341.dtd" >
+<SupplierOrder>
+<OrderId>10016</OrderId>
+<OrderDate>Wed May 29 12:45:00 PDT 2002</OrderDate>
+<ShippingAddress>
+<FirstName>ABC</FirstName>
+<LastName>XYZ</LastName>
+<Street>1234 Anywhere Street</Street>
+<City>Palo Alto</City>
+<State>California</State>
+<Country>USA</Country>
+<ZipCode>94303</ZipCode>
+<Email>NULL</Email>
+<Phone>NULL</Phone>
+</ShippingAddress>
+<LineItems>
+<LineItem categoryId="BIRDS" itemId="EST-18" lineNo="0" productId="AV-CB-01" quantity="1" unitPrice="193.5"/>
+</LineItems>
+</SupplierOrder>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4858685.txt Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,30 @@
+[document]
+ [element] env:Envelope {http://www.w3.org/2000/xmlns/}xmlns:xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:ns0="http://headertest.org/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:xsd="http://www.w3.org/2001/XMLSchema" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ [text]
+
+ [element] env:Body
+ [text]
+
+ [element] ds:X509Certificate xmlns="" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ [text]
+MIIDVjCCAxICBD6kKrMwCwYHKoZIzjgEAwUAMIGPMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex
+FDASBgNVBAcTC1NhbnRhIENsYXJhMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMR4w
+HAYDVQQLExVKYXZhIGFuZCBYTUwgU29mdHdhcmUxHDAaBgNVBAMTE0pXUy1TZWN1cml0eSBDbGll
+bnQwHhcNMDMwNDIxMTczMDI3WhcNMDMwNzIwMTczMDI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV
+BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEfMB0GA1UEChMWU3VuIE1pY3Jvc3lzdGVtcywg
+SW5jLjEeMBwGA1UECxMVSmF2YSBhbmQgWE1MIFNvZnR3YXJlMRwwGgYDVQQDExNKV1MtU2VjdXJp
+dHkgQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E
+AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up
+1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj
+C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZ
+T+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7
+zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAV3R+bUfh+u0yaPBV75umKvFB
+ucv37ETDak889b7k72kZdGoHz3oDmp69tiNDg5r7IvKtjHGbZ6C3Nv0ycNR7Sed1QPOF4nn/tgUl
+j+BvtVW3iiIRgBJ82KP+28QtwPkkxSp7n5HG0v7bE29E/juLduuhKBQTaaCvajuCFxiBrmAwCwYH
+KoZIzjgEAwUAAzEAMC4CFQCCuDNmMKjgY6MV1SmAcCdnhuT6VwIVAJBOiPDnDWp2WlKAERF6nOAf
+vKz9
+
+ [text]
+
+ [text]
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/MyErrorHandler.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXParseException;
+
+class MyErrorHandler implements ErrorHandler {
+ public void error(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+
+ public void warning(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+
+ public void fatalError(SAXParseException exception) throws SAXParseException {
+ throw exception;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/ValidationTestConst.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.validation.ptests;
+
+import static jaxp.library.JAXPTestUtilities.FILE_SEP;
+import static jaxp.library.JAXPTestUtilities.getPathByClassName;
+
+/**
+ * This class defines the path constant
+ */
+public class ValidationTestConst {
+ /**
+ * XML source file directory.
+ */
+ public static final String XML_DIR = getPathByClassName(ValidationTestConst.class,
+ ".." + FILE_SEP + "xmlfiles");
+
+ /**
+ * Golden validation files directory.
+ */
+ public static final String GOLDEN_DIR = getPathByClassName(ValidationTestConst.class,
+ ".." + FILE_SEP + "xmlfiles" + FILE_SEP + "out");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JAXPDataProvider.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jaxp.library;
+
+import org.testng.annotations.DataProvider;
+
+/**
+ * Provide invalid parameters for negative testing Factory.newInstance.
+ */
+public class JAXPDataProvider {
+
+ @DataProvider(name = "new-instance-neg")
+ public static Object[][] getNewInstanceNeg() {
+ return new Object[][] { { null, null }, { null, JAXPDataProvider.class.getClassLoader() } };
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/test/gaptest/GapTestConst.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.gaptest;
+
+import static jaxp.library.JAXPTestUtilities.FILE_SEP;
+import static jaxp.library.JAXPTestUtilities.getPathByClassName;
+
+/**
+ * This class defines the path constant
+ */
+public class GapTestConst {
+ /**
+ * XML source file directory.
+ */
+ public static final String XML_DIR = getPathByClassName(GapTestConst.class, "xmlfiles");
+
+ /**
+ * Golden validation files directory.
+ */
+ public static final String GOLDEN_DIR = getPathByClassName(GapTestConst.class, "xmlfiles" + FILE_SEP + "out");
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.xpath;
+
+import java.io.File;
+import javax.xml.xpath.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * @bug 8054196
+ * @summary Test for the project XPath: support any type. This test covers the new
+ * evaluateExpression methods of XPath, as well as XPathNodes and XPathEvaluationResult.
+ */
+public class XPathAnyTypeTest extends XPathTestBase {
+ /*
+ Test for resolveFunction(QName functionName,int arity); evaluate throws
+ NPE if functionName is null.
+ */
+
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void testCheckXPathFunctionResolver02(XPath xpath) throws XPathExpressionException {
+ xpath.setXPathFunctionResolver((functionName, arity) -> null);
+ assertEquals(xpath.evaluate(null, "5"), "2");
+ }
+ /*
+ Check that NPE is thrown when expression is null.
+ */
+
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test01(XPath xpath) throws XPathExpressionException {
+ double result = xpath.evaluateExpression(null, (Object) null, Double.class);
+ }
+
+ /*
+ Check that NPE is thrown when the class type is null.
+ */
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test02(XPath xpath) throws XPathExpressionException {
+ double result = xpath.evaluateExpression("1+1", (Object) null, null);
+ }
+
+ /*
+ Parameter item can be null when the expression does not depends on the
+ context.
+ */
+ @Test(dataProvider = "xpath")
+ public void test03(XPath xpath) throws XPathExpressionException {
+ int result = xpath.evaluateExpression("1+1", (Object) null, Integer.class);
+ assertTrue(result == 2);
+ }
+
+ /*
+ * Test return type: boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test04(XPath xpath, Document doc) throws XPathExpressionException {
+ boolean result1 = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc, Boolean.class);
+ assertTrue(result1);
+ }
+
+ /*
+ * Test return type: numeric. Subtypes supported: Double, Integer and Long
+ */
+ @Test(dataProvider = "document")
+ public void test05(XPath xpath, Document doc) throws XPathExpressionException {
+ double result1 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Double.class);
+ assertTrue(result1 == 3.0);
+ int result2 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Integer.class);
+ assertTrue(result2 == 3);
+ long result3 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Long.class);
+ assertTrue(result3 == 3);
+ }
+
+ /*
+ * Test return type: numeric. Of the subtypes of Number, only Double,
+ * Integer and Long are required.
+ */
+ @Test(dataProvider = "invalidNumericTypes", expectedExceptions = IllegalArgumentException.class)
+ public void test06(XPath xpath, Class<Number> type) throws XPathExpressionException {
+ xpath.evaluateExpression("1+1", (Object) null, type);
+ }
+
+ /*
+ * Test return type: String.
+ */
+ @Test(dataProvider = "document")
+ public void test07(XPath xpath, Document doc) throws XPathExpressionException {
+ String result1 = xpath.evaluateExpression("string(/Customers/Customer[@id=3]/Phone/text())", doc, String.class);
+ assertTrue(result1.equals("3333333333"));
+ }
+
+ /*
+ * Test return type: NodeSet.
+ */
+ @Test(dataProvider = "document")
+ public void test08(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathNodes nodes = xpath.evaluateExpression("/Customers/Customer", doc, XPathNodes.class);
+ assertTrue(nodes.size() == 3);
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), "Customer");
+ }
+ }
+
+ /*
+ * Test return type: Node.
+ */
+ @Test(dataProvider = "document")
+ public void test09(XPath xpath, Document doc) throws XPathExpressionException {
+ Node n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, Node.class);
+ assertEquals(n.getLocalName(), "Customer");
+ }
+
+ /*
+ * Test return type: Unsupported type.
+ */
+ @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class)
+ public void test10(XPath xpath, Document doc) throws XPathExpressionException {
+ File n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, File.class);
+ }
+
+ /*
+ * Test return type: Any::Boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test11(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc);
+ verifyResult(result, true);
+ }
+
+ /*
+ * Test return type: Any::Number.
+ */
+ @Test(dataProvider = "document")
+ public void test12(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("count(/Customers/Customer)", doc);
+ verifyResult(result, 3.0);
+ }
+
+ /*
+ * Test return type: Any::String.
+ */
+ @Test(dataProvider = "document")
+ public void test13(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression(
+ "string(/Customers/Customer[@id=3]/Phone/text())", doc, XPathEvaluationResult.class);
+ verifyResult(result, "3333333333");
+ }
+
+ /*
+ * Test return type: Any::Nodeset.
+ */
+ @Test(dataProvider = "document")
+ public void test14(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer", doc);
+ verifyResult(result, "Customer");
+ }
+
+ /*
+ * Test return type: Any::Node.
+ */
+ @Test(dataProvider = "document")
+ public void test15(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc);
+ verifyResult(result, "Customer");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.xml.xpath;
+
+import java.io.File;
+import javax.xml.xpath.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * @bug 8054196
+ * @summary Test for the project XPath: support any type. This test covers the new
+ * evaluateExpression methods of XPathExpression.
+ */
+public class XPathExpAnyTypeTest extends XPathTestBase {
+
+ /*
+ * Check that NPE is thrown when the class type is null.
+ */
+ @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class)
+ public void test02(XPath xpath) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("1+1");
+ double result = exp.evaluateExpression((Object)null, null);
+ }
+
+ /*
+ * Parameter item can be null when the expression does not depends on the
+ * context.
+ */
+ @Test(dataProvider = "xpath")
+ public void test03(XPath xpath) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("1+1");
+ int result = exp.evaluateExpression((Object)null, Integer.class);
+ assertTrue(result == 2);
+ }
+
+ /*
+ * Test return type: boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test04(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])");
+ boolean result1 = exp.evaluateExpression(doc, Boolean.class);
+ assertTrue(result1);
+ }
+
+ /*
+ * Test return type: numeric.
+ */
+ @Test(dataProvider = "document")
+ public void test05(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("count(/Customers/Customer)");
+ double result1 = exp.evaluateExpression(doc, Double.class);
+ assertTrue(result1 == 3.0);
+
+ int result2 = exp.evaluateExpression(doc, Integer.class);
+ assertTrue(result2 == 3);
+ }
+
+ /*
+ * Test return type: String.
+ */
+ @Test(dataProvider = "document")
+ public void test06(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())");
+ String result1 = exp.evaluateExpression(doc, String.class);
+ assertTrue(result1.equals("3333333333"));
+ }
+
+ /*
+ * Test return type: NodeSet.
+ */
+ @Test(dataProvider = "document")
+ public void test07(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer");
+ XPathNodes nodes = exp.evaluateExpression(doc, XPathNodes.class);
+ assertTrue(nodes.size() == 3);
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), "Customer");
+ }
+ }
+
+ /*
+ * Test return type: Node.
+ */
+ @Test(dataProvider = "document")
+ public void test08(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ Node n = exp.evaluateExpression(doc, Node.class);
+ assertEquals(n.getLocalName(), "Customer");
+ }
+
+ /*
+ * Test return type: Unsupported type.
+ */
+ @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class)
+ public void test09(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ File n = exp.evaluateExpression(doc, File.class);
+ }
+
+ /*
+ * Test return type: Any::Boolean.
+ */
+ @Test(dataProvider = "document")
+ public void test10(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, true);
+ }
+
+ /*
+ * Test return type: Any::Number.
+ */
+ @Test(dataProvider = "document")
+ public void test11(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("count(/Customers/Customer)");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, 3.0);
+ }
+
+ /*
+ * Test return type: Any::String.
+ */
+ @Test(dataProvider = "document")
+ public void test12(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc, XPathEvaluationResult.class);
+ verifyResult(result, "3333333333");
+ }
+
+ /*
+ * Test return type: Any::Nodeset.
+ */
+ @Test(dataProvider = "document")
+ public void test13(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, "Customer");
+ }
+
+ /*
+ * Test return type: Any::Node.
+ */
+ @Test(dataProvider = "document")
+ public void test14(XPath xpath, Document doc) throws XPathExpressionException {
+ XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]");
+ XPathEvaluationResult<?> result = exp.evaluateExpression(doc);
+ verifyResult(result, "Customer");
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package javax.xml.xpath;
+
+import java.io.ByteArrayInputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.xml.parsers.DocumentBuilderFactory;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.DataProvider;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/*
+ * Base class for XPath test
+ */
+class XPathTestBase {
+
+ static final String rawXML
+ = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
+ + "<Customers>"
+ + " <Customer id=\"1\">"
+ + " <Name>name1</Name>"
+ + " <Phone>1111111111</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>1111 111st ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + " <Customer id=\"2\">"
+ + " <Name>name1</Name>"
+ + " <Phone>2222222222</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>2222 222nd ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + " <Customer id=\"3\">"
+ + " <Name>name1</Name>"
+ + " <Phone>3333333333</Phone>"
+ + " <Email>123@xyz.com</Email>"
+ + " <Address>"
+ + " <Street>3333 333rd ave</Street>"
+ + " <City>The City</City>"
+ + " <State>The State</State>"
+ + " </Address>"
+ + " </Customer>"
+ + "</Customers>";
+
+ void verifyResult(XPathEvaluationResult<?> result, Object expected) {
+ switch (result.type()) {
+ case BOOLEAN:
+ assertTrue(((Boolean) result.value()).equals(expected));
+ return;
+ case NUMBER:
+ assertTrue(((Double) result.value()).equals(expected));
+ return;
+ case STRING:
+ assertTrue(((String) result.value()).equals(expected));
+ return;
+ case NODESET:
+ XPathNodes nodes = (XPathNodes) result.value();
+ for (Node n : nodes) {
+ assertEquals(n.getLocalName(), expected);
+ }
+ return;
+ case NODE:
+ assertTrue(((Node) result.value()).getLocalName().equals(expected));
+ return;
+ }
+ assertFalse(true, "Unsupported type");
+ }
+
+ /*
+ * DataProvider: XPath object
+ */
+ @DataProvider(name = "xpath")
+ Object[][] getXPath() {
+ return new Object[][]{{XPathFactory.newInstance().newXPath()}};
+ }
+
+ /*
+ * DataProvider: Numeric types not supported
+ */
+ @DataProvider(name = "invalidNumericTypes")
+ Object[][] getInvalidNumericTypes() {
+ XPath xpath = XPathFactory.newInstance().newXPath();
+ return new Object[][]{{xpath, AtomicInteger.class},
+ {xpath, AtomicInteger.class},
+ {xpath, AtomicLong.class},
+ {xpath, BigDecimal.class},
+ {xpath, BigInteger.class},
+ {xpath, Byte.class},
+ {xpath, Float.class},
+ {xpath, Short.class}
+ };
+ }
+
+ /*
+ * DataProvider: XPath and Document objects
+ */
+ @DataProvider(name = "document")
+ Object[][] getDocument() throws Exception {
+ DocumentBuilderFactory dBF = DocumentBuilderFactory.newInstance();
+ dBF.setValidating(false);
+ dBF.setNamespaceAware(true);
+ Document doc = dBF.newDocumentBuilder().parse(
+ new ByteArrayInputStream(rawXML.getBytes("UTF-8")));
+
+ return new Object[][]{{XPathFactory.newInstance().newXPath(), doc}};
+ }
+}
--- a/jaxws/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxws/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -293,3 +293,5 @@
e529374fbe526dbd668e5e98fc047b42b3bc6d33 jdk9-b45
64ca52b0bda8028636e4ccafbe1107befcdda47d jdk9-b46
6c17d648d03e4bf4729c3645f8db55d34115e0b7 jdk9-b47
+33e7e699804892c0496adf60ad67cc12855aeb61 jdk9-b48
+435a49db1de0589acc86b2cc5fd61d546f94b56c jdk9-b49
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java Mon Feb 09 09:52:48 2015 -0800
@@ -135,7 +135,7 @@
private void filterClass(List<Reference> classes, Collection<? extends Element> elements) {
for (Element element : elements) {
- if (element.getKind().equals(ElementKind.CLASS)) {
+ if (element.getKind().equals(ElementKind.CLASS) || element.getKind().equals(ElementKind.ENUM)) {
classes.add(new Reference((TypeElement) element, processingEnv));
filterClass(classes, ElementFilter.typesIn(element.getEnclosedElements()));
}
--- a/jdk/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45
efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46
b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47
+ebb2eb7f1aec78eb6d8cc4c96f018afa11093cde jdk9-b48
+541a8cef4e0d54c3e4b52a98c6af3c31e2096669 jdk9-b49
--- a/jdk/make/data/tzdata/VERSION Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/VERSION Mon Feb 09 09:52:48 2015 -0800
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2014j
+tzdata2015a
--- a/jdk/make/data/tzdata/antarctica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/antarctica Mon Feb 09 09:52:48 2015 -0800
@@ -70,8 +70,8 @@
Rule ChileAQ 2010 only - Apr Sun>=1 3:00u 0 -
Rule ChileAQ 2011 only - May Sun>=2 3:00u 0 -
Rule ChileAQ 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule ChileAQ 2012 max - Apr Sun>=23 3:00u 0 -
-Rule ChileAQ 2012 max - Sep Sun>=2 4:00u 1:00 S
+Rule ChileAQ 2012 2015 - Apr Sun>=23 3:00u 0 -
+Rule ChileAQ 2012 2014 - Sep Sun>=2 4:00u 1:00 S
# Argentina - year-round bases
# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -377,9 +377,10 @@
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Palmer 0 - zzz 1965
- -4:00 ArgAQ AR%sT 1969 Oct 5
+ -4:00 ArgAQ AR%sT 1969 Oct 5
-3:00 ArgAQ AR%sT 1982 May
- -4:00 ChileAQ CL%sT
+ -4:00 ChileAQ CL%sT 2015 Apr 26 3:00u
+ -3:00 - CLT
#
#
# McMurdo Station, Ross Island, since 1955-12
--- a/jdk/make/data/tzdata/asia Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/asia Mon Feb 09 09:52:48 2015 -0800
@@ -168,10 +168,7 @@
4:00 Azer AZ%sT
# Bahrain
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Bahrain 3:22:20 - LMT 1920 # Manamah
- 4:00 - GST 1972 Jun
- 3:00 - AST
+# See Asia/Qatar.
# Bangladesh
# From Alexander Krivenyshev (2009-05-13):
@@ -1754,9 +1751,7 @@
###############################################################################
# Kuwait
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Kuwait 3:11:56 - LMT 1950
- 3:00 - AST
+# See Asia/Riyadh.
# Laos
# See Asia/Bangkok.
@@ -1977,12 +1972,7 @@
5:45 - NPT # Nepal Time
# Oman
-
-# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Muscat 3:54:24 - LMT 1920
- 4:00 - GST
+# See Asia/Dubai.
# Pakistan
@@ -2476,6 +2466,7 @@
Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha
4:00 - GST 1972 Jun
3:00 - AST
+Link Asia/Qatar Asia/Bahrain
# Saudi Arabia
#
@@ -2502,6 +2493,8 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Riyadh 3:06:52 - LMT 1947 Mar 14
3:00 - AST
+Link Asia/Riyadh Asia/Aden # Yemen
+Link Asia/Riyadh Asia/Kuwait
# Singapore
# taken from Mok Ly Yng (2003-10-30)
@@ -2790,6 +2783,7 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Dubai 3:41:12 - LMT 1920
4:00 - GST
+Link Asia/Dubai Asia/Muscat # Oman
# Uzbekistan
# Byalokoz 1919 says Uzbekistan was 4:27:53.
@@ -2874,10 +2868,4 @@
7:00 - ICT
# Yemen
-
-# Milne says 2:59:54 was the meridian of the saluting battery at Aden,
-# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Aden 2:59:54 - LMT 1950
- 3:00 - AST
+# See Asia/Riyadh.
--- a/jdk/make/data/tzdata/backward Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/backward Mon Feb 09 09:52:48 2015 -0800
@@ -28,7 +28,7 @@
# and their old names. Many names changed in late 1993.
# Link TARGET LINK-NAME
-Link Africa/Asmara Africa/Asmera
+Link Africa/Nairobi Africa/Asmera
Link Africa/Abidjan Africa/Timbuktu
Link America/Argentina/Catamarca America/Argentina/ComodRivadavia
Link America/Adak America/Atka
--- a/jdk/make/data/tzdata/europe Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/europe Mon Feb 09 09:52:48 2015 -0800
@@ -1430,35 +1430,32 @@
# might be a reference to the Julian calendar as opposed to Gregorian, or it
# might mean something else (???).
#
-# From Paul Eggert (2006-03-22):
-# The Iceland Almanak, Shanks & Pottenger, and Whitman disagree on many points.
-# We go with the Almanak, except for one claim from Shanks & Pottenger, namely
-# that Reykavik was 21W57 from 1837 to 1908, local mean time before that.
+# From Paul Eggert (2014-11-22):
+# The information below is taken from the 1988 Almanak; see
+# http://www.almanak.hi.is/klukkan.html
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Iceland 1917 1918 - Feb 19 23:00 1:00 S
+Rule Iceland 1917 1919 - Feb 19 23:00 1:00 S
Rule Iceland 1917 only - Oct 21 1:00 0 -
-Rule Iceland 1918 only - Nov 16 1:00 0 -
+Rule Iceland 1918 1919 - Nov 16 1:00 0 -
+Rule Iceland 1921 only - Mar 19 23:00 1:00 S
+Rule Iceland 1921 only - Jun 23 1:00 0 -
Rule Iceland 1939 only - Apr 29 23:00 1:00 S
-Rule Iceland 1939 only - Nov 29 2:00 0 -
+Rule Iceland 1939 only - Oct 29 2:00 0 -
Rule Iceland 1940 only - Feb 25 2:00 1:00 S
-Rule Iceland 1940 only - Nov 3 2:00 0 -
-Rule Iceland 1941 only - Mar 2 1:00s 1:00 S
-Rule Iceland 1941 only - Nov 2 1:00s 0 -
-Rule Iceland 1942 only - Mar 8 1:00s 1:00 S
-Rule Iceland 1942 only - Oct 25 1:00s 0 -
+Rule Iceland 1940 1941 - Nov Sun>=2 1:00s 0 -
+Rule Iceland 1941 1942 - Mar Sun>=2 1:00s 1:00 S
# 1943-1946 - first Sunday in March until first Sunday in winter
Rule Iceland 1943 1946 - Mar Sun>=1 1:00s 1:00 S
-Rule Iceland 1943 1948 - Oct Sun>=22 1:00s 0 -
+Rule Iceland 1942 1948 - Oct Sun>=22 1:00s 0 -
# 1947-1967 - first Sunday in April until first Sunday in winter
Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 S
-# 1949 Oct transition delayed by 1 week
+# 1949 and 1967 Oct transitions delayed by 1 week
Rule Iceland 1949 only - Oct 30 1:00s 0 -
Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 -
Rule Iceland 1967 only - Oct 29 1:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Reykjavik -1:27:24 - LMT 1837
- -1:27:48 - RMT 1908 # Reykjavik Mean Time?
+Zone Atlantic/Reykjavik -1:28 - LMT 1908
-1:00 Iceland IS%sT 1968 Apr 7 1:00s
0:00 - GMT
--- a/jdk/make/data/tzdata/leapseconds Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/leapseconds Mon Feb 09 09:52:48 2015 -0800
@@ -77,3 +77,7 @@
Leap 2005 Dec 31 23:59:60 + S
Leap 2008 Dec 31 23:59:60 + S
Leap 2012 Jun 30 23:59:60 + S
+Leap 2015 Jun 30 23:59:60 + S
+
+# Updated through IERS Bulletin C49
+# File expires on: 28 December 2015
--- a/jdk/make/data/tzdata/northamerica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/northamerica Mon Feb 09 09:52:48 2015 -0800
@@ -147,7 +147,7 @@
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
-Rule US 1945 only - Sep 30 2:00 0 S
+Rule US 1945 only - Sep lastSun 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
@@ -2147,11 +2147,11 @@
# Mexico
-# From Paul Eggert (2001-03-05):
+# From Paul Eggert (2014-12-07):
# The Investigation and Analysis Service of the
# Mexican Library of Congress (MLoC) has published a
# history of Mexican local time (in Spanish)
-# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
+# http://www.diputados.gob.mx/bibliot/publica/inveyana/polisoc/horver/index.htm
#
# Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
# (In all cases we go with the MLoC.)
@@ -2320,6 +2320,24 @@
# efecto desde las dos horas del segundo domingo de marzo y concluirá a
# las dos horas del primer domingo de noviembre.
+# From Steffen Thorsen (2014-12-08), translated by Gwillim Law:
+# The Mexican state of Quintana Roo will likely change to EST in 2015.
+#
+# http://www.unioncancun.mx/articulo/2014/12/04/medio-ambiente/congreso-aprueba-una-hora-mas-de-sol-en-qroo
+# "With this change, the time conflict that has existed between the municipios
+# of Quintana Roo and the municipio of Felipe Carrillo Puerto may come to an
+# end. The latter declared itself in rebellion 15 years ago when a time change
+# was initiated in Mexico, and since then it has refused to change its time
+# zone along with the rest of the country."
+#
+# From Steffen Thorsen (2015-01-14), translated by Gwillim Law:
+# http://sipse.com/novedades/confirman-aplicacion-de-nueva-zona-horaria-para-quintana-roo-132331.html
+# "...the new time zone will come into effect at two o'clock on the first Sunday
+# of February, when we will have to advance the clock one hour from its current
+# time..."
+#
+# Also, the new zone will not use DST.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Mexico 1939 only - Feb 5 0:00 1:00 D
Rule Mexico 1939 only - Jun 25 0:00 0 S
@@ -2340,7 +2358,8 @@
Zone America/Cancun -5:47:04 - LMT 1922 Jan 1 0:12:56
-6:00 - CST 1981 Dec 23
-5:00 Mexico E%sT 1998 Aug 2 2:00
- -6:00 Mexico C%sT
+ -6:00 Mexico C%sT 2015 Feb 1 2:00
+ -5:00 - EST
# Campeche, Yucatán; represented by Mérida
Zone America/Merida -5:58:28 - LMT 1922 Jan 1 0:01:32
-6:00 - CST 1981 Dec 23
--- a/jdk/make/data/tzdata/southamerica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/southamerica Mon Feb 09 09:52:48 2015 -0800
@@ -1229,6 +1229,11 @@
# DST Start: first Saturday of September 2014 (Sun 07 Sep 2014 04:00 UTC)
# http://www.diariooficial.interior.gob.cl//media/2014/02/19/do-20140219.pdf
+# From Juan Correa (2015-01-28):
+# ... today the Ministry of Energy announced that Chile will drop DST, will keep
+# "summer time" (UTC -3 / UTC -5) all year round....
+# http://www.minenergia.cl/ministerio/noticias/generales/ministerio-de-energia-anuncia.html
+
# NOTE: ChileAQ rules for Antarctic bases are stored separately in the
# 'antarctica' file.
@@ -1270,8 +1275,8 @@
Rule Chile 2010 only - Apr Sun>=1 3:00u 0 -
Rule Chile 2011 only - May Sun>=2 3:00u 0 -
Rule Chile 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule Chile 2012 max - Apr Sun>=23 3:00u 0 -
-Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S
+Rule Chile 2012 2015 - Apr Sun>=23 3:00u 0 -
+Rule Chile 2012 2014 - Sep Sun>=2 4:00u 1:00 S
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -1282,11 +1287,13 @@
-4:00 - CLT 1919 Jul 1 # Chile Time
-4:42:46 - SMT 1927 Sep 1 # Santiago Mean Time
-5:00 Chile CL%sT 1947 May 22 # Chile Time
- -4:00 Chile CL%sT
+ -4:00 Chile CL%sT 2015 Apr 26 3:00u
+ -3:00 - CLT
Zone Pacific/Easter -7:17:44 - LMT 1890
-7:17:28 - EMT 1932 Sep # Easter Mean Time
- -7:00 Chile EAS%sT 1982 Mar 13 21:00 # Easter Time
- -6:00 Chile EAS%sT
+ -7:00 Chile EAS%sT 1982 Mar 13 3:00u # Easter Time
+ -6:00 Chile EAS%sT 2015 Apr 26 3:00u
+ -5:00 - EAST
#
# Salas y Gómez Island is uninhabited.
# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
--- a/jdk/make/data/tzdata/zone.tab Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/data/tzdata/zone.tab Mon Feb 09 09:52:48 2015 -0800
@@ -297,7 +297,7 @@
MV +0410+07330 Indian/Maldives
MW -1547+03500 Africa/Blantyre
MX +1924-09909 America/Mexico_City Central Time - most locations
-MX +2105-08646 America/Cancun Central Time - Quintana Roo
+MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo
MX +2058-08937 America/Merida Central Time - Campeche, Yucatan
MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border
MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border
--- a/jdk/make/launcher/Launcher-jdk.runtime.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/launcher/Launcher-jdk.runtime.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -66,19 +66,6 @@
ifeq ($(OPENJDK_TARGET_OS), solaris)
UNPACKEXE_LANG := C++
endif
-UNPACKEXE_DEBUG_SYMBOLS := true
-# On windows, unpack200 is linked completely differently to all other
-# executables, using the compiler with the compiler arguments.
-# It's also linked incrementally, producing a .ilk file that needs to
-# be kept away.
-ifeq ($(OPENJDK_TARGET_OS), windows)
- BUILD_UNPACKEXE_LDEXE := $(CC)
- EXE_OUT_OPTION_save := $(EXE_OUT_OPTION)
- EXE_OUT_OPTION := -Fe
- # With the current way unpack200 is built, debug symbols aren't supported
- # anyway.
- UNPACKEXE_DEBUG_SYMBOLS := false
-endif
# The linker on older SuSE distros (e.g. on SLES 10) complains with:
# "Invalid version tag `SUNWprivate_1.1'. Only anonymous version tag is allowed in executable."
@@ -93,49 +80,36 @@
SRC := $(UNPACKEXE_SRC), \
LANG := $(UNPACKEXE_LANG), \
OPTIMIZATION := LOW, \
- CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) \
- -DFULL, \
+ CFLAGS := $(UNPACKEXE_CFLAGS) $(CXXFLAGS_JDKEXE) -DFULL, \
CFLAGS_release := -DPRODUCT, \
CFLAGS_linux := -fPIC, \
CFLAGS_solaris := -KPIC, \
CFLAGS_macosx := -fPIC, \
MAPFILE := $(UNPACK_MAPFILE),\
- LDFLAGS := $(UNPACKEXE_ZIPOBJS), \
- LDFLAGS_windows := $(CXXFLAGS_JDKEXE), \
- LDFLAGS_unix := $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
+ LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
+ $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_NAME,$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX)) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_linux := -lc, \
LDFLAGS_solaris := $(UNPACKEXE_LDFLAGS_solaris) -lc, \
LDFLAGS_SUFFIX := $(LIBCXX), \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \
- OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpackexe$(OUTPUT_SUBDIR), \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE), \
PROGRAM := unpack200, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=unpack200.exe" \
-D "JDK_INTERNAL_NAME=unpack200" \
-D "JDK_FTYPE=0x1L", \
- DEBUG_SYMBOLS := $(UNPACKEXE_DEBUG_SYMBOLS), \
+ DEBUG_SYMBOLS := true, \
MANIFEST := $(JDK_TOPDIR)/src/jdk.runtime/windows/native/unpack200/unpack200_proto.exe.manifest))
-ifeq ($(OPENJDK_TARGET_OS), windows)
- EXE_OUT_OPTION := $(EXE_OUT_OPTION_save)
-endif
-
ifneq ($(USE_EXTERNAL_LIBZ), true)
$(BUILD_UNPACKEXE): $(UNPACKEXE_ZIPOBJS)
endif
-# Build into object dir and copy executable afterwards to avoid .ilk file in
-# image. The real fix would be clean up linking of unpack200 using
-# -link -incremental:no
-# like all other launchers.
-$(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/unpack200$(EXE_SUFFIX): $(BUILD_UNPACKEXE)
- $(call install-file)
-
-TARGETS += $(SUPPORT_OUTPUTDIR)/modules_cmds/$(MODULE)/unpack200$(EXE_SUFFIX)
+TARGETS += $(BUILD_UNPACKEXE)
################################################################################
--- a/jdk/make/src/classes/build/tools/module/boot.modules Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/src/classes/build/tools/module/boot.modules Mon Feb 09 09:52:48 2015 -0800
@@ -1,8 +1,6 @@
java.base
java.datatransfer
java.desktop
-java.activation
-java.annotations.common
java.compiler
java.corba
java.instrument
@@ -12,7 +10,6 @@
java.prefs
java.rmi
java.scripting
-java.security.acl
java.security.jgss
java.security.sasl
java.smartcardio
@@ -20,9 +17,7 @@
java.sql.rowset
java.transaction
java.xml
-java.xml.bind
java.xml.crypto
-java.xml.ws
jdk.charsets
jdk.deploy
jdk.deploy.osx
--- a/jdk/make/src/classes/build/tools/module/ext.modules Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/make/src/classes/build/tools/module/ext.modules Mon Feb 09 09:52:48 2015 -0800
@@ -1,3 +1,7 @@
+java.activation
+java.annotations.common
+java.xml.bind
+java.xml.ws
jdk.crypto.ec
jdk.crypto.mscapi
jdk.crypto.pkcs11
--- a/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/macosx/native/libjli/java_md_macosx.c Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1059,6 +1059,7 @@
void PostJVMInit(JNIEnv *env, jstring mainClass, JavaVM *vm) {
jvmInstance = vm;
SetMainClassForAWT(env, mainClass);
+ CHECK_EXCEPTION_RETURN();
ShowSplashScreen();
}
--- a/jdk/src/java.base/share/classes/java/lang/Number.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Number.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,7 +37,7 @@
*
* For platform classes, the conversion is often analogous to a
* narrowing primitive conversion or a widening primitive conversion
- * as defining in <cite>The Java™ Language Specification</cite>
+ * as defined in <cite>The Java™ Language Specification</cite>
* for converting between primitive types. Therefore, conversions may
* lose information about the overall magnitude of a numeric value, may
* lose precision, and may even return a result of a different sign
@@ -54,8 +54,7 @@
*/
public abstract class Number implements java.io.Serializable {
/**
- * Returns the value of the specified number as an {@code int},
- * which may involve rounding or truncation.
+ * Returns the value of the specified number as an {@code int}.
*
* @return the numeric value represented by this object after conversion
* to type {@code int}.
@@ -63,8 +62,7 @@
public abstract int intValue();
/**
- * Returns the value of the specified number as a {@code long},
- * which may involve rounding or truncation.
+ * Returns the value of the specified number as a {@code long}.
*
* @return the numeric value represented by this object after conversion
* to type {@code long}.
@@ -72,8 +70,7 @@
public abstract long longValue();
/**
- * Returns the value of the specified number as a {@code float},
- * which may involve rounding.
+ * Returns the value of the specified number as a {@code float}.
*
* @return the numeric value represented by this object after conversion
* to type {@code float}.
@@ -81,8 +78,7 @@
public abstract float floatValue();
/**
- * Returns the value of the specified number as a {@code double},
- * which may involve rounding.
+ * Returns the value of the specified number as a {@code double}.
*
* @return the numeric value represented by this object after conversion
* to type {@code double}.
@@ -90,8 +86,7 @@
public abstract double doubleValue();
/**
- * Returns the value of the specified number as a {@code byte},
- * which may involve rounding or truncation.
+ * Returns the value of the specified number as a {@code byte}.
*
* <p>This implementation returns the result of {@link #intValue} cast
* to a {@code byte}.
@@ -105,8 +100,7 @@
}
/**
- * Returns the value of the specified number as a {@code short},
- * which may involve rounding or truncation.
+ * Returns the value of the specified number as a {@code short}.
*
* <p>This implementation returns the result of {@link #intValue} cast
* to a {@code short}.
--- a/jdk/src/java.base/share/classes/java/lang/Object.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Object.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,11 @@
}
/**
+ * Constructs a new object.
+ */
+ public Object() {}
+
+ /**
* Returns the runtime class of this {@code Object}. The returned
* {@code Class} object is the object that is locked by {@code
* static synchronized} methods of the represented class.
@@ -86,12 +91,11 @@
* for unequal objects may improve the performance of hash tables.
* </ul>
* <p>
- * As much as is reasonably practical, the hashCode method defined by
- * class {@code Object} does return distinct integers for distinct
- * objects. (This is typically implemented by converting the internal
- * address of the object into an integer, but this implementation
- * technique is not required by the
- * Java™ programming language.)
+ * As much as is reasonably practical, the hashCode method defined
+ * by class {@code Object} does return distinct integers for
+ * distinct objects. (The hashCode may or may not be implemented
+ * as some function of an object's memory address at some point
+ * in time.)
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
@@ -344,10 +348,12 @@
* ... // Perform action appropriate to condition
* }
* </pre>
- * (For more information on this topic, see Section 3.2.3 in Doug Lea's
- * "Concurrent Programming in Java (Second Edition)" (Addison-Wesley,
- * 2000), or Item 50 in Joshua Bloch's "Effective Java Programming
- * Language Guide" (Addison-Wesley, 2001).
+ *
+ * (For more information on this topic, see section 14.2,
+ * Condition Queues, in Brian Goetz and others' "Java Concurrency
+ * in Practice" (Addison-Wesley, 2006) or Item 69 in Joshua
+ * Bloch's "Effective Java (Second Edition)" (Addison-Wesley,
+ * 2008).
*
* <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
* interrupted} by any thread before or while it is waiting, then an
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Mon Feb 09 09:52:48 2015 -0800
@@ -951,6 +951,9 @@
* {@code command} array as its argument. This may result in
* a {@link SecurityException} being thrown.
*
+ * <p>If the operating system does not support the creation of
+ * processes, an {@link UnsupportedOperationException} will be thrown.
+ *
* <p>Starting an operating system process is highly system-dependent.
* Among the many things that can go wrong are:
* <ul>
@@ -998,6 +1001,9 @@
*
* </ul>
*
+ * @throws UnsupportedOperationException
+ * If the operating system does not support the creation of processes.
+ *
* @throws IOException if an I/O error occurs
*
* @see Runtime#exec(String[], String[], java.io.File)
--- a/jdk/src/java.base/share/classes/java/lang/Runtime.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/Runtime.java Mon Feb 09 09:52:48 2015 -0800
@@ -564,6 +564,9 @@
* <code>cmdarray</code> as its argument. This may result in a
* {@link SecurityException} being thrown.
*
+ * <p>If the operating system does not support the creation of
+ * processes, an {@link UnsupportedOperationException} will be thrown.
+ *
* <p>Starting an operating system process is highly system-dependent.
* Among the many things that can go wrong are:
* <ul>
@@ -597,6 +600,9 @@
* {@link SecurityManager#checkExec checkExec}
* method doesn't allow creation of the subprocess
*
+ * @throws UnsupportedOperationException
+ * If the operating system does not support the creation of processes.
+ *
* @throws IOException
* If an I/O error occurs
*
--- a/jdk/src/java.base/share/classes/java/nio/channels/FileLock.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/channels/FileLock.java Mon Feb 09 09:52:48 2015 -0800
@@ -26,6 +26,7 @@
package java.nio.channels;
import java.io.IOException;
+import java.util.Objects;
/**
* A token representing a lock on a region of a file.
@@ -147,6 +148,7 @@
protected FileLock(FileChannel channel,
long position, long size, boolean shared)
{
+ Objects.requireNonNull(channel, "Null channel");
if (position < 0)
throw new IllegalArgumentException("Negative position");
if (size < 0)
@@ -185,6 +187,7 @@
protected FileLock(AsynchronousFileChannel channel,
long position, long size, boolean shared)
{
+ Objects.requireNonNull(channel, "Null channel");
if (position < 0)
throw new IllegalArgumentException("Negative position");
if (size < 0)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/Acl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * Interface representing an Access Control List (ACL). An Access
+ * Control List is a data structure used to guard access to
+ * resources.<p>
+ *
+ * An ACL can be thought of as a data structure with multiple ACL
+ * entries. Each ACL entry, of interface type AclEntry, contains a
+ * set of permissions associated with a particular principal. (A
+ * principal represents an entity such as an individual user or a
+ * group). Additionally, each ACL entry is specified as being either
+ * positive or negative. If positive, the permissions are to be
+ * granted to the associated principal. If negative, the permissions
+ * are to be denied.<p>
+ *
+ * The ACL Entries in each ACL observe the following rules:
+ *
+ * <ul> <li>Each principal can have at most one positive ACL entry and
+ * one negative entry; that is, multiple positive or negative ACL
+ * entries are not allowed for any principal. Each entry specifies
+ * the set of permissions that are to be granted (if positive) or
+ * denied (if negative).
+ *
+ * <li>If there is no entry for a particular principal, then the
+ * principal is considered to have a null (empty) permission set.
+ *
+ * <li>If there is a positive entry that grants a principal a
+ * particular permission, and a negative entry that denies the
+ * principal the same permission, the result is as though the
+ * permission was never granted or denied.
+ *
+ * <li>Individual permissions always override permissions of the
+ * group(s) to which the individual belongs. That is, individual
+ * negative permissions (specific denial of permissions) override the
+ * groups' positive permissions. And individual positive permissions
+ * override the groups' negative permissions.
+ *
+ * </ul>
+ *
+ * The {@code java.security.acl } package provides the
+ * interfaces to the ACL and related data structures (ACL entries,
+ * groups, permissions, etc.), and the {@code sun.security.acl }
+ * classes provide a default implementation of the interfaces. For
+ * example, {@code java.security.acl.Acl } provides the
+ * interface to an ACL and the {@code sun.security.acl.AclImpl }
+ * class provides the default implementation of the interface.<p>
+ *
+ * The {@code java.security.acl.Acl } interface extends the
+ * {@code java.security.acl.Owner } interface. The Owner
+ * interface is used to maintain a list of owners for each ACL. Only
+ * owners are allowed to modify an ACL. For example, only an owner can
+ * call the ACL's {@code addEntry} method to add a new ACL entry
+ * to the ACL.
+ *
+ * @see java.security.acl.AclEntry
+ * @see java.security.acl.Owner
+ * @see java.security.acl.Acl#getPermissions
+ *
+ * @author Satish Dharmaraj
+ */
+
+public interface Acl extends Owner {
+
+ /**
+ * Sets the name of this ACL.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param name the name to be given to this ACL.
+ *
+ * @exception NotOwnerException if the caller principal
+ * is not an owner of this ACL.
+ *
+ * @see #getName
+ */
+ public void setName(Principal caller, String name)
+ throws NotOwnerException;
+
+ /**
+ * Returns the name of this ACL.
+ *
+ * @return the name of this ACL.
+ *
+ * @see #setName
+ */
+ public String getName();
+
+ /**
+ * Adds an ACL entry to this ACL. An entry associates a principal
+ * (e.g., an individual or a group) with a set of
+ * permissions. Each principal can have at most one positive ACL
+ * entry (specifying permissions to be granted to the principal)
+ * and one negative ACL entry (specifying permissions to be
+ * denied). If there is already an ACL entry of the same type
+ * (negative or positive) already in the ACL, false is returned.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param entry the ACL entry to be added to this ACL.
+ *
+ * @return true on success, false if an entry of the same type
+ * (positive or negative) for the same principal is already
+ * present in this ACL.
+ *
+ * @exception NotOwnerException if the caller principal
+ * is not an owner of this ACL.
+ */
+ public boolean addEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * Removes an ACL entry from this ACL.
+ *
+ * @param caller the principal invoking this method. It must be an
+ * owner of this ACL.
+ *
+ * @param entry the ACL entry to be removed from this ACL.
+ *
+ * @return true on success, false if the entry is not part of this ACL.
+ *
+ * @exception NotOwnerException if the caller principal is not
+ * an owner of this Acl.
+ */
+ public boolean removeEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException;
+
+ /**
+ * Returns an enumeration for the set of allowed permissions for the
+ * specified principal (representing an entity such as an individual or
+ * a group). This set of allowed permissions is calculated as
+ * follows:
+ *
+ * <ul>
+ *
+ * <li>If there is no entry in this Access Control List for the
+ * specified principal, an empty permission set is returned.
+ *
+ * <li>Otherwise, the principal's group permission sets are determined.
+ * (A principal can belong to one or more groups, where a group is a
+ * group of principals, represented by the Group interface.)
+ * The group positive permission set is the union of all
+ * the positive permissions of each group that the principal belongs to.
+ * The group negative permission set is the union of all
+ * the negative permissions of each group that the principal belongs to.
+ * If there is a specific permission that occurs in both
+ * the positive permission set and the negative permission set,
+ * it is removed from both.<p>
+ *
+ * The individual positive and negative permission sets are also
+ * determined. The positive permission set contains the permissions
+ * specified in the positive ACL entry (if any) for the principal.
+ * Similarly, the negative permission set contains the permissions
+ * specified in the negative ACL entry (if any) for the principal.
+ * The individual positive (or negative) permission set is considered
+ * to be null if there is not a positive (negative) ACL entry for the
+ * principal in this ACL.<p>
+ *
+ * The set of permissions granted to the principal is then calculated
+ * using the simple rule that individual permissions always override
+ * the group permissions. That is, the principal's individual negative
+ * permission set (specific denial of permissions) overrides the group
+ * positive permission set, and the principal's individual positive
+ * permission set overrides the group negative permission set.
+ *
+ * </ul>
+ *
+ * @param user the principal whose permission set is to be returned.
+ *
+ * @return the permission set specifying the permissions the principal
+ * is allowed.
+ */
+ public Enumeration<Permission> getPermissions(Principal user);
+
+ /**
+ * Returns an enumeration of the entries in this ACL. Each element in
+ * the enumeration is of type AclEntry.
+ *
+ * @return an enumeration of the entries in this ACL.
+ */
+ public Enumeration<AclEntry> entries();
+
+ /**
+ * Checks whether or not the specified principal has the specified
+ * permission. If it does, true is returned, otherwise false is returned.
+ *
+ * More specifically, this method checks whether the passed permission
+ * is a member of the allowed permission set of the specified principal.
+ * The allowed permission set is determined by the same algorithm as is
+ * used by the {@code getPermissions} method.
+ *
+ * @param principal the principal, assumed to be a valid authenticated
+ * Principal.
+ *
+ * @param permission the permission to be checked for.
+ *
+ * @return true if the principal has the specified permission, false
+ * otherwise.
+ *
+ * @see #getPermissions
+ */
+ public boolean checkPermission(Principal principal, Permission permission);
+
+ /**
+ * Returns a string representation of the
+ * ACL contents.
+ *
+ * @return a string representation of the ACL contents.
+ */
+ public String toString();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclEntry.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * This is the interface used for representing one entry in an Access
+ * Control List (ACL).<p>
+ *
+ * An ACL can be thought of as a data structure with multiple ACL entry
+ * objects. Each ACL entry object contains a set of permissions associated
+ * with a particular principal. (A principal represents an entity such as
+ * an individual user or a group). Additionally, each ACL entry is specified
+ * as being either positive or negative. If positive, the permissions are
+ * to be granted to the associated principal. If negative, the permissions
+ * are to be denied. Each principal can have at most one positive ACL entry
+ * and one negative entry; that is, multiple positive or negative ACL
+ * entries are not allowed for any principal.
+ *
+ * Note: ACL entries are by default positive. An entry becomes a
+ * negative entry only if the
+ * {@link #setNegativePermissions() setNegativePermissions}
+ * method is called on it.
+ *
+ * @see java.security.acl.Acl
+ *
+ * @author Satish Dharmaraj
+ */
+public interface AclEntry extends Cloneable {
+
+ /**
+ * Specifies the principal for which permissions are granted or denied
+ * by this ACL entry. If a principal was already set for this ACL entry,
+ * false is returned, otherwise true is returned.
+ *
+ * @param user the principal to be set for this entry.
+ *
+ * @return true if the principal is set, false if there was
+ * already a principal set for this entry.
+ *
+ * @see #getPrincipal
+ */
+ public boolean setPrincipal(Principal user);
+
+ /**
+ * Returns the principal for which permissions are granted or denied by
+ * this ACL entry. Returns null if there is no principal set for this
+ * entry yet.
+ *
+ * @return the principal associated with this entry.
+ *
+ * @see #setPrincipal
+ */
+ public Principal getPrincipal();
+
+ /**
+ * Sets this ACL entry to be a negative one. That is, the associated
+ * principal (e.g., a user or a group) will be denied the permission set
+ * specified in the entry.
+ *
+ * Note: ACL entries are by default positive. An entry becomes a
+ * negative entry only if this {@code setNegativePermissions}
+ * method is called on it.
+ */
+ public void setNegativePermissions();
+
+ /**
+ * Returns true if this is a negative ACL entry (one denying the
+ * associated principal the set of permissions in the entry), false
+ * otherwise.
+ *
+ * @return true if this is a negative ACL entry, false if it's not.
+ */
+ public boolean isNegative();
+
+ /**
+ * Adds the specified permission to this ACL entry. Note: An entry can
+ * have multiple permissions.
+ *
+ * @param permission the permission to be associated with
+ * the principal in this entry.
+ *
+ * @return true if the permission was added, false if the
+ * permission was already part of this entry's permission set.
+ */
+ public boolean addPermission(Permission permission);
+
+ /**
+ * Removes the specified permission from this ACL entry.
+ *
+ * @param permission the permission to be removed from this entry.
+ *
+ * @return true if the permission is removed, false if the
+ * permission was not part of this entry's permission set.
+ */
+ public boolean removePermission(Permission permission);
+
+ /**
+ * Checks if the specified permission is part of the
+ * permission set in this entry.
+ *
+ * @param permission the permission to be checked for.
+ *
+ * @return true if the permission is part of the
+ * permission set in this entry, false otherwise.
+ */
+ public boolean checkPermission(Permission permission);
+
+ /**
+ * Returns an enumeration of the permissions in this ACL entry.
+ *
+ * @return an enumeration of the permissions in this ACL entry.
+ */
+ public Enumeration<Permission> permissions();
+
+ /**
+ * Returns a string representation of the contents of this ACL entry.
+ *
+ * @return a string representation of the contents.
+ */
+ public String toString();
+
+ /**
+ * Clones this ACL entry.
+ *
+ * @return a clone of this ACL entry.
+ */
+ public Object clone();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/AclNotFoundException.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.security.acl;
+
+/**
+ * This is an exception that is thrown whenever a reference is made to a
+ * non-existent ACL (Access Control List).
+ *
+ * @author Satish Dharmaraj
+ */
+public class AclNotFoundException extends Exception {
+
+ private static final long serialVersionUID = 5684295034092681791L;
+
+ /**
+ * Constructs an AclNotFoundException.
+ */
+ public AclNotFoundException() {
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/Group.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.util.Enumeration;
+import java.security.Principal;
+
+/**
+ * This interface is used to represent a group of principals. (A principal
+ * represents an entity such as an individual user or a company). <p>
+ *
+ * Note that Group extends Principal. Thus, either a Principal or a Group can
+ * be passed as an argument to methods containing a Principal parameter. For
+ * example, you can add either a Principal or a Group to a Group object by
+ * calling the object's {@code addMember} method, passing it the
+ * Principal or Group.
+ *
+ * @author Satish Dharmaraj
+ */
+public interface Group extends Principal {
+
+ /**
+ * Adds the specified member to the group.
+ *
+ * @param user the principal to add to this group.
+ *
+ * @return true if the member was successfully added,
+ * false if the principal was already a member.
+ */
+ public boolean addMember(Principal user);
+
+ /**
+ * Removes the specified member from the group.
+ *
+ * @param user the principal to remove from this group.
+ *
+ * @return true if the principal was removed, or
+ * false if the principal was not a member.
+ */
+ public boolean removeMember(Principal user);
+
+ /**
+ * Returns true if the passed principal is a member of the group.
+ * This method does a recursive search, so if a principal belongs to a
+ * group which is a member of this group, true is returned.
+ *
+ * @param member the principal whose membership is to be checked.
+ *
+ * @return true if the principal is a member of this group,
+ * false otherwise.
+ */
+ public boolean isMember(Principal member);
+
+
+ /**
+ * Returns an enumeration of the members in the group.
+ * The returned objects can be instances of either Principal
+ * or Group (which is a subclass of Principal).
+ *
+ * @return an enumeration of the group members.
+ */
+ public Enumeration<? extends Principal> members();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/LastOwnerException.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.security.acl;
+
+/**
+ * This is an exception that is thrown whenever an attempt is made to delete
+ * the last owner of an Access Control List.
+ *
+ * @see java.security.acl.Owner#deleteOwner
+ *
+ * @author Satish Dharmaraj
+ */
+public class LastOwnerException extends Exception {
+
+ private static final long serialVersionUID = -5141997548211140359L;
+
+ /**
+ * Constructs a LastOwnerException.
+ */
+ public LastOwnerException() {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/NotOwnerException.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute 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.security.acl;
+
+/**
+ * This is an exception that is thrown whenever the modification of an object
+ * (such as an Access Control List) is only allowed to be done by an owner of
+ * the object, but the Principal attempting the modification is not an owner.
+ *
+ * @author Satish Dharmaraj
+ */
+public class NotOwnerException extends Exception {
+
+ private static final long serialVersionUID = -5555597911163362399L;
+
+ /**
+ * Constructs a NotOwnerException.
+ */
+ public NotOwnerException() {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/Owner.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+import java.security.Principal;
+
+/**
+ * Interface for managing owners of Access Control Lists (ACLs) or ACL
+ * configurations. (Note that the Acl interface in the
+ * {@code java.security.acl} package extends this Owner
+ * interface.) The initial owner Principal should be specified as an
+ * argument to the constructor of the class implementing this interface.
+ *
+ * @see java.security.acl.Acl
+ *
+ */
+public interface Owner {
+
+ /**
+ * Adds an owner. Only owners can modify ACL contents. The caller
+ * principal must be an owner of the ACL in order to invoke this method.
+ * That is, only an owner can add another owner. The initial owner is
+ * configured at ACL construction time.
+ *
+ * @param caller the principal invoking this method. It must be an owner
+ * of the ACL.
+ *
+ * @param owner the owner that should be added to the list of owners.
+ *
+ * @return true if successful, false if owner is already an owner.
+ * @exception NotOwnerException if the caller principal is not an owner
+ * of the ACL.
+ */
+ public boolean addOwner(Principal caller, Principal owner)
+ throws NotOwnerException;
+
+ /**
+ * Deletes an owner. If this is the last owner in the ACL, an exception is
+ * raised.<p>
+ *
+ * The caller principal must be an owner of the ACL in order to invoke
+ * this method.
+ *
+ * @param caller the principal invoking this method. It must be an owner
+ * of the ACL.
+ *
+ * @param owner the owner to be removed from the list of owners.
+ *
+ * @return true if the owner is removed, false if the owner is not part
+ * of the list of owners.
+ *
+ * @exception NotOwnerException if the caller principal is not an owner
+ * of the ACL.
+ *
+ * @exception LastOwnerException if there is only one owner left, so that
+ * deleteOwner would leave the ACL owner-less.
+ */
+ public boolean deleteOwner(Principal caller, Principal owner)
+ throws NotOwnerException, LastOwnerException;
+
+ /**
+ * Returns true if the given principal is an owner of the ACL.
+ *
+ * @param owner the principal to be checked to determine whether or not
+ * it is an owner.
+ *
+ * @return true if the passed principal is in the list of owners, false
+ * if not.
+ */
+ public boolean isOwner(Principal owner);
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/Permission.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.security.acl;
+
+
+/**
+ * This interface represents a permission, such as that used to grant
+ * a particular type of access to a resource.
+ *
+ * @author Satish Dharmaraj
+ */
+public interface Permission {
+
+ /**
+ * Returns true if the object passed matches the permission represented
+ * in this interface.
+ *
+ * @param another the Permission object to compare with.
+ *
+ * @return true if the Permission objects are equal, false otherwise
+ */
+ public boolean equals(Object another);
+
+ /**
+ * Prints a string representation of this permission.
+ *
+ * @return the string representation of the permission.
+ */
+ public String toString();
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/java/security/acl/package-info.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * The classes and interfaces in this package have been
+ * superseded by classes in the java.security package.
+ * See that package and, for example, java.security.Permission for details.
+ *
+ * @since 1.1
+ */
+package java.security.acl;
--- a/jdk/src/java.base/share/classes/java/time/Clock.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/Clock.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -61,12 +61,15 @@
*/
package java.time;
+import java.io.IOException;
+import java.io.ObjectInputStream;
import static java.time.LocalTime.NANOS_PER_MINUTE;
import static java.time.LocalTime.NANOS_PER_SECOND;
import java.io.Serializable;
import java.util.Objects;
import java.util.TimeZone;
+import sun.misc.VM;
/**
* A clock providing access to the current instant, date and time using a time-zone.
@@ -446,10 +449,22 @@
*/
static final class SystemClock extends Clock implements Serializable {
private static final long serialVersionUID = 6740630888130243051L;
+ private static final long OFFSET_SEED =
+ System.currentTimeMillis()/1000 - 1024; // initial offest
private final ZoneId zone;
+ // We don't actually need a volatile here.
+ // We don't care if offset is set or read concurrently by multiple
+ // threads - we just need a value which is 'recent enough' - in other
+ // words something that has been updated at least once in the last
+ // 2^32 secs (~136 years). And even if we by chance see an invalid
+ // offset, the worst that can happen is that we will get a -1 value
+ // from getNanoTimeAdjustment, forcing us to update the offset
+ // once again.
+ private transient long offset;
SystemClock(ZoneId zone) {
this.zone = zone;
+ this.offset = OFFSET_SEED;
}
@Override
public ZoneId getZone() {
@@ -464,11 +479,50 @@
}
@Override
public long millis() {
+ // System.currentTimeMillis() and VM.getNanoTimeAdjustment(offset)
+ // use the same time source - System.currentTimeMillis() simply
+ // limits the resolution to milliseconds.
+ // So we take the faster path and call System.currentTimeMillis()
+ // directly - in order to avoid the performance penalty of
+ // VM.getNanoTimeAdjustment(offset) which is less efficient.
return System.currentTimeMillis();
}
@Override
public Instant instant() {
- return Instant.ofEpochMilli(millis());
+ // Take a local copy of offset. offset can be updated concurrently
+ // by other threads (even if we haven't made it volatile) so we will
+ // work with a local copy.
+ long localOffset = offset;
+ long adjustment = VM.getNanoTimeAdjustment(localOffset);
+
+ if (adjustment == -1) {
+ // -1 is a sentinel value returned by VM.getNanoTimeAdjustment
+ // when the offset it is given is too far off the current UTC
+ // time. In principle, this should not happen unless the
+ // JVM has run for more than ~136 years (not likely) or
+ // someone is fiddling with the system time, or the offset is
+ // by chance at 1ns in the future (very unlikely).
+ // We can easily recover from all these conditions by bringing
+ // back the offset in range and retry.
+
+ // bring back the offset in range. We use -1024 to make
+ // it more unlikely to hit the 1ns in the future condition.
+ localOffset = System.currentTimeMillis()/1000 - 1024;
+
+ // retry
+ adjustment = VM.getNanoTimeAdjustment(localOffset);
+
+ if (adjustment == -1) {
+ // Should not happen: we just recomputed a new offset.
+ // It should have fixed the issue.
+ throw new InternalError("Offset " + localOffset + " is not in range");
+ } else {
+ // OK - recovery succeeded. Update the offset for the
+ // next call...
+ offset = localOffset;
+ }
+ }
+ return Instant.ofEpochSecond(localOffset, adjustment);
}
@Override
public boolean equals(Object obj) {
@@ -485,6 +539,12 @@
public String toString() {
return "SystemClock[" + zone + "]";
}
+ private void readObject(ObjectInputStream is)
+ throws IOException, ClassNotFoundException {
+ // ensure that offset is initialized
+ is.defaultReadObject();
+ offset = OFFSET_SEED;
+ }
}
//-----------------------------------------------------------------------
--- a/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/chrono/Chronology.java Mon Feb 09 09:52:48 2015 -0800
@@ -538,7 +538,14 @@
* <ul>
* <li>a leap-year must imply a year-length longer than a non leap-year.
* <li>a chronology that does not support the concept of a year must return false.
+ * <li>the correct result must be returned for all years within the
+ * valid range of years for the chronology.
* </ul>
+ * <p>
+ * Outside the range of valid years an implementation is free to return
+ * either a best guess or false.
+ * An implementation must not throw an exception, even if the year is
+ * outside the range of valid years.
*
* @param prolepticYear the proleptic-year to check, not validated for range
* @return true if the year is a leap year
--- a/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/chrono/HijrahChronology.java Mon Feb 09 09:52:48 2015 -0800
@@ -475,10 +475,10 @@
@Override
public boolean isLeapYear(long prolepticYear) {
checkCalendarInit();
+ if (prolepticYear < getMinimumYear() || prolepticYear > getMaximumYear()) {
+ return false;
+ }
int epochMonth = yearToEpochMonth((int) prolepticYear);
- if (epochMonth < 0 || epochMonth > maxEpochDay) {
- throw new DateTimeException("Hijrah date out of range");
- }
int len = getYearLength((int) prolepticYear);
return (len > 354);
}
--- a/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/chrono/JapaneseEra.java Mon Feb 09 09:52:48 2015 -0800
@@ -195,10 +195,11 @@
* @throws DateTimeException if the value is invalid
*/
public static JapaneseEra of(int japaneseEra) {
- if (japaneseEra < MEIJI.eraValue || japaneseEra + ERA_OFFSET > KNOWN_ERAS.length) {
+ int i = ordinal(japaneseEra);
+ if (i < 0 || i >= KNOWN_ERAS.length) {
throw new DateTimeException("Invalid era: " + japaneseEra);
}
- return KNOWN_ERAS[ordinal(japaneseEra)];
+ return KNOWN_ERAS[i];
}
/**
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatter.java Mon Feb 09 09:52:48 2015 -0800
@@ -117,8 +117,9 @@
* {@code parse(CharSequence text, DateTimeFormatter formatter)}.
* <p>For example:
* <blockquote><pre>
+ * LocalDate date = LocalDate.now();
* String text = date.format(formatter);
- * LocalDate date = LocalDate.parse(text, formatter);
+ * LocalDate parsedDate = LocalDate.parse(text, formatter);
* </pre></blockquote>
* <p>
* In addition to the format, formatters can be created with desired Locale,
@@ -265,9 +266,10 @@
* <p>
* For example:
* <blockquote><pre>
+ * LocalDate date = LocalDate.now();
* DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
* String text = date.format(formatter);
- * LocalDate date = LocalDate.parse(text, formatter);
+ * LocalDate parsedDate = LocalDate.parse(text, formatter);
* </pre></blockquote>
* <p>
* All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The
--- a/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java Mon Feb 09 09:52:48 2015 -0800
@@ -849,6 +849,7 @@
* @param fractionalDigits the number of fractional second digits to format with,
* from 0 to 9, or -1 to use as many digits as necessary
* @return this, for chaining, not null
+ * @throws IllegalArgumentException if the number of fractional digits is invalid
*/
public DateTimeFormatterBuilder appendInstant(int fractionalDigits) {
if (fractionalDigits < -1 || fractionalDigits > 9) {
@@ -909,6 +910,7 @@
* @param pattern the pattern to use, not null
* @param noOffsetText the text to use when the offset is zero, not null
* @return this, for chaining, not null
+ * @throws IllegalArgumentException if the pattern is invalid
*/
public DateTimeFormatterBuilder appendOffset(String pattern, String noOffsetText) {
appendInternal(new OffsetIdPrinterParser(pattern, noOffsetText));
--- a/jdk/src/java.base/share/classes/java/time/package-info.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/time/package-info.java Mon Feb 09 09:52:48 2015 -0800
@@ -65,7 +65,7 @@
* The main API for dates, times, instants, and durations.
* </p>
* <p>
- * The classes defined here represent the principal date-time concepts,
+ * The classes defined here represent the principle date-time concepts,
* including instants, durations, dates, times, time-zones and periods.
* They are based on the ISO calendar system, which is the <i>de facto</i> world
* calendar following the proleptic Gregorian rules.
@@ -247,8 +247,8 @@
* </ul>
* <p>
* Multiple calendar systems is an awkward addition to the design challenges.
- * The first principal is that most users want the standard ISO calendar system.
- * As such, the main classes are ISO-only. The second principal is that most of those that want a
+ * The first principle is that most users want the standard ISO calendar system.
+ * As such, the main classes are ISO-only. The second principle is that most of those that want a
* non-ISO calendar system want it for user interaction, thus it is a UI localization issue.
* As such, date and time objects should be held as ISO objects in the data model and persistent
* storage, only being converted to and from a local calendar for display.
--- a/jdk/src/java.base/share/classes/java/util/Formatter.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Formatter.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,6 +57,7 @@
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalQueries;
+import java.time.temporal.UnsupportedTemporalTypeException;
import sun.misc.DoubleConsts;
import sun.misc.FormattedFloatingDecimal;
@@ -4056,7 +4057,12 @@
break;
}
case DateTime.NANOSECOND: { // 'N' (000000000 - 999999999)
- int i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000;
+ int i;
+ try {
+ i = t.get(ChronoField.NANO_OF_SECOND);
+ } catch (UnsupportedTemporalTypeException u) {
+ i = t.get(ChronoField.MILLI_OF_SECOND) * 1000000;
+ }
Flags flags = Flags.ZERO_PAD;
sb.append(localizedMagnitude(null, i, flags, 9, l));
break;
--- a/jdk/src/java.base/share/classes/java/util/Optional.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/Optional.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
+import java.util.stream.Stream;
/**
* A container object which may or may not contain a non-null value.
@@ -155,8 +156,9 @@
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
- if (value != null)
+ if (value != null) {
consumer.accept(value);
+ }
}
/**
@@ -172,10 +174,11 @@
*/
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
- if (!isPresent())
+ if (!isPresent()) {
return this;
- else
+ } else {
return predicate.test(value) ? this : empty();
+ }
}
/**
@@ -209,9 +212,9 @@
*/
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
- if (!isPresent())
+ if (!isPresent()) {
return empty();
- else {
+ } else {
return Optional.ofNullable(mapper.apply(value));
}
}
@@ -235,14 +238,37 @@
*/
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
- if (!isPresent())
+ if (!isPresent()) {
return empty();
- else {
+ } else {
return Objects.requireNonNull(mapper.apply(value));
}
}
/**
+ * If a value is present return a sequential {@link Stream} containing only
+ * that value, otherwise return an empty {@code Stream}.
+ *
+ * @apiNote This method can be used to transform a {@code Stream} of
+ * optional elements to a {@code Stream} of present value elements:
+ *
+ * <pre>{@code
+ * Stream<Optional<T>> os = ..
+ * Stream<T> s = os.flatMap(Optional::stream)
+ * }</pre>
+ *
+ * @return the optional value as a {@code Stream}
+ * @since 1.9
+ */
+ public Stream<T> stream() {
+ if (!isPresent()) {
+ return Stream.empty();
+ } else {
+ return Stream.of(value);
+ }
+ }
+
+ /**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
--- a/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalDouble.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.util.function.DoubleConsumer;
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
+import java.util.stream.DoubleStream;
/**
* A container object which may or may not contain a {@code double} value.
@@ -138,8 +139,32 @@
* null
*/
public void ifPresent(DoubleConsumer consumer) {
- if (isPresent)
+ if (isPresent) {
consumer.accept(value);
+ }
+ }
+
+ /**
+ * If a value is present return a sequential {@link DoubleStream} containing
+ * only that value, otherwise return an empty {@code DoubleStream}.
+ *
+ * @apiNote This method can be used to transform a {@code Stream} of
+ * optional doubles to a {@code DoubleStream} of present doubles:
+ *
+ * <pre>{@code
+ * Stream<OptionalDouble> os = ..
+ * DoubleStream s = os.flatMapToDouble(OptionalDouble::stream)
+ * }</pre>
+ *
+ * @return the optional value as a {@code DoubleStream}
+ * @since 1.9
+ */
+ public DoubleStream stream() {
+ if (isPresent) {
+ return DoubleStream.of(value);
+ } else {
+ return DoubleStream.empty();
+ }
}
/**
@@ -182,7 +207,7 @@
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
- public<X extends Throwable> double orElseThrow(Supplier<X> exceptionSupplier) throws X {
+ public<X extends Throwable> double orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
--- a/jdk/src/java.base/share/classes/java/util/OptionalInt.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalInt.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.util.function.IntConsumer;
import java.util.function.IntSupplier;
import java.util.function.Supplier;
+import java.util.stream.IntStream;
/**
* A container object which may or may not contain a {@code int} value.
@@ -138,8 +139,32 @@
* null
*/
public void ifPresent(IntConsumer consumer) {
- if (isPresent)
+ if (isPresent) {
consumer.accept(value);
+ }
+ }
+
+ /**
+ * If a value is present return a sequential {@link IntStream} containing
+ * only that value, otherwise return an empty {@code IntStream}.
+ *
+ * @apiNote This method can be used to transform a {@code Stream} of
+ * optional integers to an {@code IntStream} of present integers:
+ *
+ * <pre>{@code
+ * Stream<OptionalInt> os = ..
+ * IntStream s = os.flatMapToInt(OptionalInt::stream)
+ * }</pre>
+ *
+ * @return the optional value as an {@code IntStream}
+ * @since 1.9
+ */
+ public IntStream stream() {
+ if (isPresent) {
+ return IntStream.of(value);
+ } else {
+ return IntStream.empty();
+ }
}
/**
@@ -182,7 +207,7 @@
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
- public<X extends Throwable> int orElseThrow(Supplier<X> exceptionSupplier) throws X {
+ public<X extends Throwable> int orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
--- a/jdk/src/java.base/share/classes/java/util/OptionalLong.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/OptionalLong.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
import java.util.function.LongConsumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
+import java.util.stream.LongStream;
/**
* A container object which may or may not contain a {@code long} value.
@@ -138,8 +139,32 @@
* null
*/
public void ifPresent(LongConsumer consumer) {
- if (isPresent)
+ if (isPresent) {
consumer.accept(value);
+ }
+ }
+
+ /**
+ * If a value is present return a sequential {@link LongStream} containing
+ * only that value, otherwise return an empty {@code LongStream}.
+ *
+ * @apiNote This method can be used to transform a {@code Stream} of
+ * optional longs to a {@code LongStream} of present longs:
+ *
+ * <pre>{@code
+ * Stream<OptionalLong> os = ..
+ * LongStream s = os.flatMapToLong(OptionalLong::stream)
+ * }</pre>
+ *
+ * @return the optional value as a {@code LongStream}
+ * @since 1.9
+ */
+ public LongStream stream() {
+ if (isPresent) {
+ return LongStream.of(value);
+ } else {
+ return LongStream.empty();
+ }
}
/**
@@ -182,7 +207,7 @@
* @throws NullPointerException if no value is present and
* {@code exceptionSupplier} is null
*/
- public<X extends Throwable> long orElseThrow(Supplier<X> exceptionSupplier) throws X {
+ public<X extends Throwable> long orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (isPresent) {
return value;
} else {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/TimeUnit.java Mon Feb 09 09:52:48 2015 -0800
@@ -131,6 +131,7 @@
/**
* Time unit representing sixty seconds
+ * @since 1.6
*/
MINUTES {
public long toNanos(long d) { return x(d, C4/C0, MAX/(C4/C0)); }
@@ -146,6 +147,7 @@
/**
* Time unit representing sixty minutes
+ * @since 1.6
*/
HOURS {
public long toNanos(long d) { return x(d, C5/C0, MAX/(C5/C0)); }
@@ -161,6 +163,7 @@
/**
* Time unit representing twenty four hours
+ * @since 1.6
*/
DAYS {
public long toNanos(long d) { return x(d, C6/C0, MAX/(C6/C0)); }
--- a/jdk/src/java.base/share/classes/java/util/stream/BaseStream.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/java/util/stream/BaseStream.java Mon Feb 09 09:52:48 2015 -0800
@@ -79,6 +79,14 @@
* <p>This is a <a href="package-summary.html#StreamOps">terminal
* operation</a>.
*
+ * <p>
+ * The returned spliterator should report the set of characteristics derived
+ * from the stream pipeline (namely the characteristics derived from the
+ * stream source spliterator and the intermediate operations).
+ * Implementations may report a sub-set of those characteristics. For
+ * example, it may be too expensive to compute the entire set for some or
+ * all possible stream pipelines.
+ *
* @return the element spliterator for this stream
*/
Spliterator<T> spliterator();
--- a/jdk/src/java.base/share/classes/sun/misc/VM.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/misc/VM.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -402,6 +402,36 @@
*/
public static native long getegid();
+ /**
+ * Get a nanosecond time stamp adjustment in the form of a single long.
+ *
+ * This value can be used to create an instant using
+ * {@link java.time.Instant#ofEpochSecond(long, long)
+ * java.time.Instant.ofEpochSecond(offsetInSeconds,
+ * getNanoTimeAdjustment(offsetInSeconds))}.
+ * <p>
+ * The value returned has the best resolution available to the JVM on
+ * the current system.
+ * This is usually down to microseconds - or tenth of microseconds -
+ * depending on the OS/Hardware and the JVM implementation.
+ *
+ * @param offsetInSeconds The offset in seconds from which the nanosecond
+ * time stamp should be computed.
+ *
+ * @apiNote The offset should be recent enough - so that
+ * {@code offsetInSeconds} is within {@code +/- 2^32} seconds of the
+ * current UTC time. If the offset is too far off, {@code -1} will be
+ * returned. As such, {@code -1} must not be considered as a valid
+ * nano time adjustment, but as an exception value indicating
+ * that an offset closer to the current time should be used.
+ *
+ * @return A nanosecond time stamp adjustment in the form of a single long.
+ * If the offset is too far off the current time, this method returns -1.
+ * In that case, the caller should call this method again, passing a
+ * more accurate offset.
+ */
+ public static native long getNanoTimeAdjustment(long offsetInSeconds);
+
static {
initialize();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/AclEntryImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.security.acl;
+
+import java.util.*;
+import java.security.Principal;
+import java.security.acl.*;
+
+/**
+ * This is a class that describes one entry that associates users
+ * or groups with permissions in the ACL.
+ * The entry may be used as a way of granting or denying permissions.
+ * @author Satish Dharmaraj
+ */
+public class AclEntryImpl implements AclEntry {
+ private Principal user = null;
+ private Vector<Permission> permissionSet = new Vector<>(10, 10);
+ private boolean negative = false;
+
+ /**
+ * Construct an ACL entry that associates a user with permissions
+ * in the ACL.
+ * @param user The user that is associated with this entry.
+ */
+ public AclEntryImpl(Principal user) {
+ this.user = user;
+ }
+
+ /**
+ * Construct a null ACL entry
+ */
+ public AclEntryImpl() {
+ }
+
+ /**
+ * Sets the principal in the entity. If a group or a
+ * principal had already been set, a false value is
+ * returned, otherwise a true value is returned.
+ * @param user The user that is associated with this entry.
+ * @return true if the principal is set, false if there is
+ * one already.
+ */
+ public boolean setPrincipal(Principal user) {
+ if (this.user != null)
+ return false;
+ this.user = user;
+ return true;
+ }
+
+ /**
+ * This method sets the ACL to have negative permissions.
+ * That is the user or group is denied the permission set
+ * specified in the entry.
+ */
+ public void setNegativePermissions() {
+ negative = true;
+ }
+
+ /**
+ * Returns true if this is a negative ACL.
+ */
+ public boolean isNegative() {
+ return negative;
+ }
+
+ /**
+ * A principal or a group can be associated with multiple
+ * permissions. This method adds a permission to the ACL entry.
+ * @param permission The permission to be associated with
+ * the principal or the group in the entry.
+ * @return true if the permission was added, false if the
+ * permission was already part of the permission set.
+ */
+ public boolean addPermission(Permission permission) {
+
+ if (permissionSet.contains(permission))
+ return false;
+
+ permissionSet.addElement(permission);
+
+ return true;
+ }
+
+ /**
+ * The method disassociates the permission from the Principal
+ * or the Group in this ACL entry.
+ * @param permission The permission to be disassociated with
+ * the principal or the group in the entry.
+ * @return true if the permission is removed, false if the
+ * permission is not part of the permission set.
+ */
+ public boolean removePermission(Permission permission) {
+ return permissionSet.removeElement(permission);
+ }
+
+ /**
+ * Checks if the passed permission is part of the allowed
+ * permission set in this entry.
+ * @param permission The permission that has to be part of
+ * the permission set in the entry.
+ * @return true if the permission passed is part of the
+ * permission set in the entry, false otherwise.
+ */
+ public boolean checkPermission(Permission permission) {
+ return permissionSet.contains(permission);
+ }
+
+ /**
+ * return an enumeration of the permissions in this ACL entry.
+ */
+ public Enumeration<Permission> permissions() {
+ return permissionSet.elements();
+ }
+
+ /**
+ * Return a string representation of the contents of the ACL entry.
+ */
+ public String toString() {
+ StringBuffer s = new StringBuffer();
+ if (negative)
+ s.append("-");
+ else
+ s.append("+");
+ if (user instanceof Group)
+ s.append("Group.");
+ else
+ s.append("User.");
+ s.append(user + "=");
+ Enumeration<Permission> e = permissions();
+ while(e.hasMoreElements()) {
+ Permission p = e.nextElement();
+ s.append(p);
+ if (e.hasMoreElements())
+ s.append(",");
+ }
+ return new String(s);
+ }
+
+ /**
+ * Clones an AclEntry.
+ */
+ @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
+ public synchronized Object clone() {
+ AclEntryImpl cloned;
+ cloned = new AclEntryImpl(user);
+ cloned.permissionSet = (Vector<Permission>) permissionSet.clone();
+ cloned.negative = negative;
+ return cloned;
+ }
+
+ /**
+ * Return the Principal associated in this ACL entry.
+ * The method returns null if the entry uses a group
+ * instead of a principal.
+ */
+ public Principal getPrincipal() {
+ return user;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/AclImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,408 @@
+/*
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.io.*;
+import java.util.*;
+import java.security.Principal;
+import java.security.acl.*;
+
+/**
+ * An Access Control List (ACL) is encapsulated by this class.
+ * @author Satish Dharmaraj
+ */
+public class AclImpl extends OwnerImpl implements Acl {
+ //
+ // Maintain four tables. one each for positive and negative
+ // ACLs. One each depending on whether the entity is a group
+ // or principal.
+ //
+ private Hashtable<Principal, AclEntry> allowedUsersTable =
+ new Hashtable<>(23);
+ private Hashtable<Principal, AclEntry> allowedGroupsTable =
+ new Hashtable<>(23);
+ private Hashtable<Principal, AclEntry> deniedUsersTable =
+ new Hashtable<>(23);
+ private Hashtable<Principal, AclEntry> deniedGroupsTable =
+ new Hashtable<>(23);
+ private String aclName = null;
+ private Vector<Permission> zeroSet = new Vector<>(1,1);
+
+
+ /**
+ * Constructor for creating an empty ACL.
+ */
+ public AclImpl(Principal owner, String name) {
+ super(owner);
+ try {
+ setName(owner, name);
+ } catch (Exception e) {}
+ }
+
+ /**
+ * Sets the name of the ACL.
+ * @param caller the principal who is invoking this method.
+ * @param name the name of the ACL.
+ * @exception NotOwnerException if the caller principal is
+ * not on the owners list of the Acl.
+ */
+ public void setName(Principal caller, String name)
+ throws NotOwnerException
+ {
+ if (!isOwner(caller))
+ throw new NotOwnerException();
+
+ aclName = name;
+ }
+
+ /**
+ * Returns the name of the ACL.
+ * @return the name of the ACL.
+ */
+ public String getName() {
+ return aclName;
+ }
+
+ /**
+ * Adds an ACL entry to this ACL. An entry associates a
+ * group or a principal with a set of permissions. Each
+ * user or group can have one positive ACL entry and one
+ * negative ACL entry. If there is one of the type (negative
+ * or positive) already in the table, a false value is returned.
+ * The caller principal must be a part of the owners list of
+ * the ACL in order to invoke this method.
+ * @param caller the principal who is invoking this method.
+ * @param entry the ACL entry that must be added to the ACL.
+ * @return true on success, false if the entry is already present.
+ * @exception NotOwnerException if the caller principal
+ * is not on the owners list of the Acl.
+ */
+ public synchronized boolean addEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException
+ {
+ if (!isOwner(caller))
+ throw new NotOwnerException();
+
+ Hashtable<Principal, AclEntry> aclTable = findTable(entry);
+ Principal key = entry.getPrincipal();
+
+ if (aclTable.get(key) != null)
+ return false;
+
+ aclTable.put(key, entry);
+ return true;
+ }
+
+ /**
+ * Removes an ACL entry from this ACL.
+ * The caller principal must be a part of the owners list of the ACL
+ * in order to invoke this method.
+ * @param caller the principal who is invoking this method.
+ * @param entry the ACL entry that must be removed from the ACL.
+ * @return true on success, false if the entry is not part of the ACL.
+ * @exception NotOwnerException if the caller principal is not
+ * the owners list of the Acl.
+ */
+ public synchronized boolean removeEntry(Principal caller, AclEntry entry)
+ throws NotOwnerException
+ {
+ if (!isOwner(caller))
+ throw new NotOwnerException();
+
+ Hashtable<Principal, AclEntry> aclTable = findTable(entry);
+ Principal key = entry.getPrincipal();
+
+ AclEntry o = aclTable.remove(key);
+ return (o != null);
+ }
+
+ /**
+ * This method returns the set of allowed permissions for the
+ * specified principal. This set of allowed permissions is calculated
+ * as follows:
+ *
+ * If there is no entry for a group or a principal an empty permission
+ * set is assumed.
+ *
+ * The group positive permission set is the union of all
+ * the positive permissions of each group that the individual belongs to.
+ * The group negative permission set is the union of all
+ * the negative permissions of each group that the individual belongs to.
+ * If there is a specific permission that occurs in both
+ * the postive permission set and the negative permission set,
+ * it is removed from both. The group positive and negatoive permission
+ * sets are calculated.
+ *
+ * The individial positive permission set and the individual negative
+ * permission set is then calculated. Again abscence of an entry means
+ * the empty set.
+ *
+ * The set of permissions granted to the principal is then calculated using
+ * the simple rule: Individual permissions always override the Group permissions.
+ * Specifically, individual negative permission set (specific
+ * denial of permissions) overrides the group positive permission set.
+ * And the individual positive permission set override the group negative
+ * permission set.
+ *
+ * @param user the principal for which the ACL entry is returned.
+ * @return The resulting permission set that the principal is allowed.
+ */
+ public synchronized Enumeration<Permission> getPermissions(Principal user) {
+
+ Enumeration<Permission> individualPositive;
+ Enumeration<Permission> individualNegative;
+ Enumeration<Permission> groupPositive;
+ Enumeration<Permission> groupNegative;
+
+ //
+ // canonicalize the sets. That is remove common permissions from
+ // positive and negative sets.
+ //
+ groupPositive =
+ subtract(getGroupPositive(user), getGroupNegative(user));
+ groupNegative =
+ subtract(getGroupNegative(user), getGroupPositive(user));
+ individualPositive =
+ subtract(getIndividualPositive(user), getIndividualNegative(user));
+ individualNegative =
+ subtract(getIndividualNegative(user), getIndividualPositive(user));
+
+ //
+ // net positive permissions is individual positive permissions
+ // plus (group positive - individual negative).
+ //
+ Enumeration<Permission> temp1 =
+ subtract(groupPositive, individualNegative);
+ Enumeration<Permission> netPositive =
+ union(individualPositive, temp1);
+
+ // recalculate the enumeration since we lost it in performing the
+ // subtraction
+ //
+ individualPositive =
+ subtract(getIndividualPositive(user), getIndividualNegative(user));
+ individualNegative =
+ subtract(getIndividualNegative(user), getIndividualPositive(user));
+
+ //
+ // net negative permissions is individual negative permissions
+ // plus (group negative - individual positive).
+ //
+ temp1 = subtract(groupNegative, individualPositive);
+ Enumeration<Permission> netNegative = union(individualNegative, temp1);
+
+ return subtract(netPositive, netNegative);
+ }
+
+ /**
+ * This method checks whether or not the specified principal
+ * has the required permission. If permission is denied
+ * permission false is returned, a true value is returned otherwise.
+ * This method does not authenticate the principal. It presumes that
+ * the principal is a valid authenticated principal.
+ * @param principal the name of the authenticated principal
+ * @param permission the permission that the principal must have.
+ * @return true of the principal has the permission desired, false
+ * otherwise.
+ */
+ public boolean checkPermission(Principal principal, Permission permission)
+ {
+ Enumeration<Permission> permSet = getPermissions(principal);
+ while (permSet.hasMoreElements()) {
+ Permission p = permSet.nextElement();
+ if (p.equals(permission))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * returns an enumeration of the entries in this ACL.
+ */
+ public synchronized Enumeration<AclEntry> entries() {
+ return new AclEnumerator(this,
+ allowedUsersTable, allowedGroupsTable,
+ deniedUsersTable, deniedGroupsTable);
+ }
+
+ /**
+ * return a stringified version of the
+ * ACL.
+ */
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ Enumeration<AclEntry> entries = entries();
+ while (entries.hasMoreElements()) {
+ AclEntry entry = entries.nextElement();
+ sb.append(entry.toString().trim());
+ sb.append("\n");
+ }
+
+ return sb.toString();
+ }
+
+ //
+ // Find the table that this entry belongs to. There are 4
+ // tables that are maintained. One each for postive and
+ // negative ACLs and one each for groups and users.
+ // This method figures out which
+ // table is the one that this AclEntry belongs to.
+ //
+ private Hashtable<Principal, AclEntry> findTable(AclEntry entry) {
+ Hashtable<Principal, AclEntry> aclTable = null;
+
+ Principal p = entry.getPrincipal();
+ if (p instanceof Group) {
+ if (entry.isNegative())
+ aclTable = deniedGroupsTable;
+ else
+ aclTable = allowedGroupsTable;
+ } else {
+ if (entry.isNegative())
+ aclTable = deniedUsersTable;
+ else
+ aclTable = allowedUsersTable;
+ }
+ return aclTable;
+ }
+
+ //
+ // returns the set e1 U e2.
+ //
+ private static Enumeration<Permission> union(Enumeration<Permission> e1,
+ Enumeration<Permission> e2) {
+ Vector<Permission> v = new Vector<>(20, 20);
+
+ while (e1.hasMoreElements())
+ v.addElement(e1.nextElement());
+
+ while (e2.hasMoreElements()) {
+ Permission o = e2.nextElement();
+ if (!v.contains(o))
+ v.addElement(o);
+ }
+
+ return v.elements();
+ }
+
+ //
+ // returns the set e1 - e2.
+ //
+ private Enumeration<Permission> subtract(Enumeration<Permission> e1,
+ Enumeration<Permission> e2) {
+ Vector<Permission> v = new Vector<>(20, 20);
+
+ while (e1.hasMoreElements())
+ v.addElement(e1.nextElement());
+
+ while (e2.hasMoreElements()) {
+ Permission o = e2.nextElement();
+ if (v.contains(o))
+ v.removeElement(o);
+ }
+
+ return v.elements();
+ }
+
+ private Enumeration<Permission> getGroupPositive(Principal user) {
+ Enumeration<Permission> groupPositive = zeroSet.elements();
+ Enumeration<Principal> e = allowedGroupsTable.keys();
+ while (e.hasMoreElements()) {
+ Group g = (Group)e.nextElement();
+ if (g.isMember(user)) {
+ AclEntry ae = allowedGroupsTable.get(g);
+ groupPositive = union(ae.permissions(), groupPositive);
+ }
+ }
+ return groupPositive;
+ }
+
+ private Enumeration<Permission> getGroupNegative(Principal user) {
+ Enumeration<Permission> groupNegative = zeroSet.elements();
+ Enumeration<Principal> e = deniedGroupsTable.keys();
+ while (e.hasMoreElements()) {
+ Group g = (Group)e.nextElement();
+ if (g.isMember(user)) {
+ AclEntry ae = deniedGroupsTable.get(g);
+ groupNegative = union(ae.permissions(), groupNegative);
+ }
+ }
+ return groupNegative;
+ }
+
+ private Enumeration<Permission> getIndividualPositive(Principal user) {
+ Enumeration<Permission> individualPositive = zeroSet.elements();
+ AclEntry ae = allowedUsersTable.get(user);
+ if (ae != null)
+ individualPositive = ae.permissions();
+ return individualPositive;
+ }
+
+ private Enumeration<Permission> getIndividualNegative(Principal user) {
+ Enumeration<Permission> individualNegative = zeroSet.elements();
+ AclEntry ae = deniedUsersTable.get(user);
+ if (ae != null)
+ individualNegative = ae.permissions();
+ return individualNegative;
+ }
+}
+
+final class AclEnumerator implements Enumeration<AclEntry> {
+ Acl acl;
+ Enumeration<AclEntry> u1, u2, g1, g2;
+
+ AclEnumerator(Acl acl, Hashtable<?,AclEntry> u1, Hashtable<?,AclEntry> g1,
+ Hashtable<?,AclEntry> u2, Hashtable<?,AclEntry> g2) {
+ this.acl = acl;
+ this.u1 = u1.elements();
+ this.u2 = u2.elements();
+ this.g1 = g1.elements();
+ this.g2 = g2.elements();
+ }
+
+ public boolean hasMoreElements() {
+ return (u1.hasMoreElements() ||
+ u2.hasMoreElements() ||
+ g1.hasMoreElements() ||
+ g2.hasMoreElements());
+ }
+
+ public AclEntry nextElement()
+ {
+ AclEntry o;
+ synchronized (acl) {
+ if (u1.hasMoreElements())
+ return u1.nextElement();
+ if (u2.hasMoreElements())
+ return u2.nextElement();
+ if (g1.hasMoreElements())
+ return g1.nextElement();
+ if (g2.hasMoreElements())
+ return g2.nextElement();
+ }
+ throw new NoSuchElementException("Acl Enumerator");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/AllPermissionsImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.security.Principal;
+import java.security.acl.*;
+
+/**
+ * This class implements the principal interface for the set of all permissions.
+ * @author Satish Dharmaraj
+ */
+public class AllPermissionsImpl extends PermissionImpl {
+
+ public AllPermissionsImpl(String s) {
+ super(s);
+ }
+
+ /**
+ * This function returns true if the permission passed matches the permission represented in
+ * this interface.
+ * @param another The Permission object to compare with.
+ * @returns true always
+ */
+ public boolean equals(Permission another) {
+ return true;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/GroupImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.util.*;
+import java.security.*;
+import java.security.acl.*;
+
+/**
+ * This class implements a group of principals.
+ * @author Satish Dharmaraj
+ */
+public class GroupImpl implements Group {
+ private Vector<Principal> groupMembers = new Vector<>(50, 100);
+ private String group;
+
+ /**
+ * Constructs a Group object with no members.
+ * @param groupName the name of the group
+ */
+ public GroupImpl(String groupName) {
+ this.group = groupName;
+ }
+
+ /**
+ * adds the specified member to the group.
+ * @param user The principal to add to the group.
+ * @return true if the member was added - false if the
+ * member could not be added.
+ */
+ public boolean addMember(Principal user) {
+ if (groupMembers.contains(user))
+ return false;
+
+ // do not allow groups to be added to itself.
+ if (group.equals(user.toString()))
+ throw new IllegalArgumentException();
+
+ groupMembers.addElement(user);
+ return true;
+ }
+
+ /**
+ * removes the specified member from the group.
+ * @param user The principal to remove from the group.
+ * @param true if the principal was removed false if
+ * the principal was not a member
+ */
+ public boolean removeMember(Principal user) {
+ return groupMembers.removeElement(user);
+ }
+
+ /**
+ * returns the enumeration of the members in the group.
+ */
+ public Enumeration<? extends Principal> members() {
+ return groupMembers.elements();
+ }
+
+ /**
+ * This function returns true if the group passed matches
+ * the group represented in this interface.
+ * @param another The group to compare this group to.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Group == false) {
+ return false;
+ }
+ Group another = (Group)obj;
+ return group.equals(another.toString());
+ }
+
+ // equals(Group) for compatibility
+ public boolean equals(Group another) {
+ return equals((Object)another);
+ }
+
+ /**
+ * Prints a stringified version of the group.
+ */
+ public String toString() {
+ return group;
+ }
+
+ /**
+ * return a hashcode for the principal.
+ */
+ public int hashCode() {
+ return group.hashCode();
+ }
+
+ /**
+ * returns true if the passed principal is a member of the group.
+ * @param member The principal whose membership must be checked for.
+ * @return true if the principal is a member of this group,
+ * false otherwise
+ */
+ public boolean isMember(Principal member) {
+
+ //
+ // if the member is part of the group (common case), return true.
+ // if not, recursively search depth first in the group looking for the
+ // principal.
+ //
+ if (groupMembers.contains(member)) {
+ return true;
+ } else {
+ Vector<Group> alreadySeen = new Vector<>(10);
+ return isMemberRecurse(member, alreadySeen);
+ }
+ }
+
+ /**
+ * return the name of the principal.
+ */
+ public String getName() {
+ return group;
+ }
+
+ //
+ // This function is the recursive search of groups for this
+ // implementation of the Group. The search proceeds building up
+ // a vector of already seen groups. Only new groups are considered,
+ // thereby avoiding loops.
+ //
+ boolean isMemberRecurse(Principal member, Vector<Group> alreadySeen) {
+ Enumeration<? extends Principal> e = members();
+ while (e.hasMoreElements()) {
+ boolean mem = false;
+ Principal p = (Principal) e.nextElement();
+
+ // if the member is in this collection, return true
+ if (p.equals(member)) {
+ return true;
+ } else if (p instanceof GroupImpl) {
+ //
+ // if not recurse if the group has not been checked already.
+ // Can call method in this package only if the object is an
+ // instance of this class. Otherwise call the method defined
+ // in the interface. (This can lead to a loop if a mixture of
+ // implementations form a loop, but we live with this improbable
+ // case rather than clutter the interface by forcing the
+ // implementation of this method.)
+ //
+ GroupImpl g = (GroupImpl) p;
+ alreadySeen.addElement(this);
+ if (!alreadySeen.contains(g))
+ mem = g.isMemberRecurse(member, alreadySeen);
+ } else if (p instanceof Group) {
+ Group g = (Group) p;
+ if (!alreadySeen.contains(g))
+ mem = g.isMember(member);
+ }
+
+ if (mem)
+ return mem;
+ }
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/OwnerImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.util.*;
+import java.security.*;
+import java.security.acl.*;
+
+/**
+ * Class implementing the Owner interface. The
+ * initial owner principal is configured as
+ * part of the constructor.
+ * @author Satish Dharmaraj
+ */
+public class OwnerImpl implements Owner {
+ private Group ownerGroup;
+
+ public OwnerImpl(Principal owner) {
+ ownerGroup = new GroupImpl("AclOwners");
+ ownerGroup.addMember(owner);
+ }
+
+ /**
+ * Adds an owner. Owners can modify ACL contents and can disassociate
+ * ACLs from the objects they protect in the AclConfig interface.
+ * The caller principal must be a part of the owners list of the ACL in
+ * order to invoke this method. The initial owner is configured
+ * at ACL construction time.
+ * @param caller the principal who is invoking this method.
+ * @param owner The owner that should be added to the owners list.
+ * @return true if success, false if already an owner.
+ * @exception NotOwnerException if the caller principal is not on
+ * the owners list of the Acl.
+ */
+ public synchronized boolean addOwner(Principal caller, Principal owner)
+ throws NotOwnerException
+ {
+ if (!isOwner(caller))
+ throw new NotOwnerException();
+
+ ownerGroup.addMember(owner);
+ return false;
+ }
+
+ /**
+ * Delete owner. If this is the last owner in the ACL, an exception is
+ * raised.
+ * The caller principal must be a part of the owners list of the ACL in
+ * order to invoke this method.
+ * @param caller the principal who is invoking this method.
+ * @param owner The owner to be removed from the owners list.
+ * @return true if the owner is removed, false if the owner is not part
+ * of the owners list.
+ * @exception NotOwnerException if the caller principal is not on
+ * the owners list of the Acl.
+ * @exception LastOwnerException if there is only one owner left in the group, then
+ * deleteOwner would leave the ACL owner-less. This exception is raised in such a case.
+ */
+ public synchronized boolean deleteOwner(Principal caller, Principal owner)
+ throws NotOwnerException, LastOwnerException
+ {
+ if (!isOwner(caller))
+ throw new NotOwnerException();
+
+ Enumeration<? extends Principal> e = ownerGroup.members();
+ //
+ // check if there is atleast 2 members left.
+ //
+ Object o = e.nextElement();
+ if (e.hasMoreElements())
+ return ownerGroup.removeMember(owner);
+ else
+ throw new LastOwnerException();
+
+ }
+
+ /**
+ * returns if the given principal belongs to the owner list.
+ * @param owner The owner to check if part of the owners list
+ * @return true if the passed principal is in the owner list, false if not.
+ */
+ public synchronized boolean isOwner(Principal owner) {
+ return ownerGroup.isMember(owner);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/PermissionImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.security.Principal;
+import java.security.acl.*;
+
+/**
+ * The PermissionImpl class implements the permission
+ * interface for permissions that are strings.
+ * @author Satish Dharmaraj
+ */
+public class PermissionImpl implements Permission {
+
+ private String permission;
+
+ /**
+ * Construct a permission object using a string.
+ * @param permission the stringified version of the permission.
+ */
+ public PermissionImpl(String permission) {
+ this.permission = permission;
+ }
+
+ /**
+ * This function returns true if the object passed matches the permission
+ * represented in this interface.
+ * @param another The Permission object to compare with.
+ * @return true if the Permission objects are equal, false otherwise
+ */
+ public boolean equals(Object another) {
+ if (another instanceof Permission) {
+ Permission p = (Permission) another;
+ return permission.equals(p.toString());
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Prints a stringified version of the permission.
+ * @return the string representation of the Permission.
+ */
+ public String toString() {
+ return permission;
+ }
+
+ /**
+ * Returns a hashcode for this PermissionImpl.
+ *
+ * @return a hashcode for this PermissionImpl.
+ */
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/PrincipalImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.security.*;
+
+/**
+ * This class implements the principal interface.
+ *
+ * @author Satish Dharmaraj
+ */
+public class PrincipalImpl implements Principal {
+
+ private String user;
+
+ /**
+ * Construct a principal from a string user name.
+ * @param user The string form of the principal name.
+ */
+ public PrincipalImpl(String user) {
+ this.user = user;
+ }
+
+ /**
+ * This function returns true if the object passed matches
+ * the principal represented in this implementation
+ * @param another the Principal to compare with.
+ * @return true if the Principal passed is the same as that
+ * encapsulated in this object, false otherwise
+ */
+ public boolean equals(Object another) {
+ if (another instanceof PrincipalImpl) {
+ PrincipalImpl p = (PrincipalImpl) another;
+ return user.equals(p.toString());
+ } else
+ return false;
+ }
+
+ /**
+ * Prints a stringified version of the principal.
+ */
+ public String toString() {
+ return user;
+ }
+
+ /**
+ * return a hashcode for the principal.
+ */
+ public int hashCode() {
+ return user.hashCode();
+ }
+
+ /**
+ * return the name of the principal.
+ */
+ public String getName() {
+ return user;
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/acl/WorldGroupImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.acl;
+
+import java.security.*;
+
+/**
+ * This class implements a group of principals.
+ * @author Satish Dharmaraj
+ */
+public class WorldGroupImpl extends GroupImpl {
+
+ public WorldGroupImpl(String s) {
+ super(s);
+ }
+
+ /**
+ * returns true for all passed principals
+ * @param member The principal whose membership must be checked in this Group.
+ * @return true always since this is the "world" group.
+ */
+ public boolean isMember(Principal member) {
+ return true;
+ }
+}
--- a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -408,7 +408,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Venezuela Time", "VET",
"Venezuela Summer Time", "VEST",
"Venezuela Time", "VET"}},
--- a/jdk/src/java.base/share/conf/security/java.policy Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/conf/security/java.policy Mon Feb 09 09:52:48 2015 -0800
@@ -55,6 +55,29 @@
permission java.io.FilePermission "<<ALL FILES>>", "read";
};
+grant codeBase "jrt:/java.xml.ws" {
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.org.apache.xerces.internal.*";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.util.PropertyPermission "*", "read";
+};
+
+grant codeBase "jrt:/java.xml.bind" {
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.xml.internal.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal";
+ permission java.lang.RuntimePermission "accessClassInPackage.com.sun.istack.internal.*";
+ permission java.lang.RuntimePermission "accessDeclaredMembers";
+ permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
+ permission java.util.PropertyPermission "*", "read";
+};
+
+grant codeBase "jrt:/java.activation" {
+ permission java.security.AllPermission;
+};
+
// default permissions granted to all domains
grant {
--- a/jdk/src/java.base/share/native/include/jvm.h Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/native/include/jvm.h Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,6 +104,9 @@
JNIEXPORT jlong JNICALL
JVM_NanoTime(JNIEnv *env, jclass ignored);
+JNIEXPORT jlong JNICALL
+JVM_GetNanoTimeAdjustment(JNIEnv *env, jclass ignored, jlong offset_secs);
+
JNIEXPORT void JNICALL
JVM_ArrayCopy(JNIEnv *env, jclass ignored, jobject src, jint src_pos,
jobject dst, jint dst_pos, jint length);
--- a/jdk/src/java.base/share/native/libjava/VM.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/native/libjava/VM.c Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,11 @@
#include "sun_misc_VM.h"
+/* Only register the performance-critical methods */
+static JNINativeMethod methods[] = {
+ {"getNanoTimeAdjustment", "(J)J", (void *)&JVM_GetNanoTimeAdjustment}
+};
+
JNIEXPORT jobject JNICALL
Java_sun_misc_VM_latestUserDefinedLoader(JNIEnv *env, jclass cls) {
return JVM_LatestUserDefinedLoader(env);
@@ -49,6 +54,14 @@
return;
}
+ // Registers implementations of native methods described in methods[]
+ // above.
+ // In particular, registers JVM_GetNanoTimeAdjustment as the implementation
+ // of the native sun.misc.VM.getNanoTimeAdjustment - avoiding the cost of
+ // introducing a Java_sun_misc_VM_getNanoTimeAdjustment wrapper
+ (*env)->RegisterNatives(env, cls,
+ methods, sizeof(methods)/sizeof(methods[0]));
+
func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo");
if (func_p != NULL) {
jvm_version_info info;
--- a/jdk/src/java.base/share/native/libjli/java.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/native/libjli/java.c Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -350,12 +350,6 @@
} \
} while (JNI_FALSE)
-#define CHECK_EXCEPTION_RETURN() \
- do { \
- if ((*env)->ExceptionOccurred(env)) { \
- return; \
- } \
- } while (JNI_FALSE)
int JNICALL
JavaMain(void * _args)
@@ -466,6 +460,7 @@
* of the application class.
*/
PostJVMInit(env, appClass, vm);
+ CHECK_EXCEPTION_LEAVE(1);
/*
* The LoadMainClass not only loads the main class, it will also ensure
* that the main method's signature is correct, therefore further checking
--- a/jdk/src/java.base/share/native/libjli/java.h Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/share/native/libjli/java.h Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -254,4 +254,11 @@
#define NULL_CHECK(NC_check_pointer) \
NULL_CHECK_RETURN_VALUE(NC_check_pointer, )
+#define CHECK_EXCEPTION_RETURN() \
+ do { \
+ if ((*env)->ExceptionOccurred(env)) { \
+ return; \
+ } \
+ } while (JNI_FALSE)
+
#endif /* _JAVA_H_ */
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsPath.java Mon Feb 09 09:52:48 2015 -0800
@@ -391,6 +391,10 @@
if (!this.root.equalsIgnoreCase(other.root))
throw new IllegalArgumentException("'other' has different root");
+ // this path is the empty path
+ if (this.isEmpty())
+ return other;
+
int bn = this.getNameCount();
int cn = other.getNameCount();
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c Mon Feb 09 09:52:48 2015 -0800
@@ -296,6 +296,8 @@
return -1;
}
+ SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
+
ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c Mon Feb 09 09:52:48 2015 -0800
@@ -699,6 +699,7 @@
}
return;
}
+ SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
if (him.him.sa_family == AF_INET) {
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c Mon Feb 09 09:52:48 2015 -0800
@@ -105,6 +105,7 @@
return IOS_THROWN;
}
+ SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
(*env)->SetIntField(env, newfdo, fd_fdID, newfd);
remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,25 @@
+#
+# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+com.sun.management.internal.PlatformMBeanProviderImpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.sun.management.internal;
+
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.management.DynamicMBean;
+import javax.management.ObjectName;
+import sun.management.ManagementFactoryHelper;
+import sun.management.spi.PlatformMBeanProvider;
+
+public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider {
+ private final List<PlatformComponent<?>> mxbeanList;
+
+ public PlatformMBeanProviderImpl() {
+ mxbeanList = Collections.unmodifiableList(init());
+ }
+
+ @Override
+ public List<PlatformComponent<?>> getPlatformComponentList() {
+ return mxbeanList;
+ }
+
+ private List<PlatformComponent<?>> init() {
+ ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>();
+ /**
+ * Garbage Collector in the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<java.lang.management.MemoryManagerMXBean>() {
+ private final Set<String> garbageCollectorMXBeanInterfaceNames
+ = Collections.unmodifiableSet(
+ Stream.of("java.lang.management.MemoryManagerMXBean",
+ "java.lang.management.GarbageCollectorMXBean",
+ "com.sun.management.GarbageCollectorMXBean")
+ .collect(Collectors.toSet()));
+
+ @Override
+ public Set<Class<? extends java.lang.management.MemoryManagerMXBean>> mbeanInterfaces() {
+ return Stream.of(java.lang.management.MemoryManagerMXBean.class,
+ java.lang.management.GarbageCollectorMXBean.class,
+ com.sun.management.GarbageCollectorMXBean.class)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return garbageCollectorMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*";
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false; // zero or more instances
+ }
+
+ @Override
+ public Map<String, java.lang.management.MemoryManagerMXBean> nameToMBeanMap() {
+ List<java.lang.management.GarbageCollectorMXBean> list
+ = ManagementFactoryHelper.getGarbageCollectorMXBeans();;
+ Map<String, java.lang.management.MemoryManagerMXBean> map;
+ if (list.isEmpty()) {
+ map = Collections.<String, java.lang.management.MemoryManagerMXBean>emptyMap();
+ } else {
+ map = new HashMap<>(list.size());
+ for (java.lang.management.MemoryManagerMXBean gcm : list) {
+ map.put(gcm.getObjectName().getCanonicalName(),
+ gcm);
+ }
+ }
+ return map;
+ }
+ });
+
+ /**
+ * OperatingSystemMXBean
+ */
+ initMBeanList.add(new PlatformComponent<java.lang.management.OperatingSystemMXBean>() {
+ private final Set<String> operatingSystemMXBeanInterfaceNames
+ = Collections.unmodifiableSet(
+ Stream.of("java.lang.management.OperatingSystemMXBean",
+ "com.sun.management.OperatingSystemMXBean",
+ "com.sun.management.UnixOperatingSystemMXBean")
+ .collect(Collectors.toSet()));
+
+ @Override
+ public Set<Class<? extends java.lang.management.OperatingSystemMXBean>> mbeanInterfaces() {
+ return Stream.of(java.lang.management.OperatingSystemMXBean.class,
+ com.sun.management.OperatingSystemMXBean.class,
+ com.sun.management.UnixOperatingSystemMXBean.class)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return operatingSystemMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() {
+ return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap(
+ ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
+ ManagementFactoryHelper.getOperatingSystemMXBean());
+ }
+ });
+
+ /**
+ * Diagnostic support for the HotSpot Virtual Machine.
+ */
+ initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() {
+ private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames =
+ Collections.unmodifiableSet(Collections.<String>singleton("com.sun.management.HotSpotDiagnosticMXBean"));
+
+ @Override
+ public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() {
+ return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return hotSpotDiagnosticMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return "com.sun.management:type=HotSpotDiagnostic";
+ }
+
+ @Override
+ public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() {
+ return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap(
+ "com.sun.management:type=HotSpotDiagnostic",
+ ManagementFactoryHelper.getDiagnosticMXBean());
+ }
+ });
+
+ /**
+ * DynamicMBean
+ */
+ HashMap<ObjectName, DynamicMBean> dynmbeans
+ = ManagementFactoryHelper.getPlatformDynamicMBeans();
+ final Set<String> dynamicMBeanInterfaceNames =
+ Collections.unmodifiableSet(Collections.<String>singleton("javax.management.DynamicMBean"));
+ for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
+ initMBeanList.add(new PlatformComponent<DynamicMBean>() {
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return dynamicMBeanInterfaceNames;
+ }
+
+ @Override
+ public Set<Class<? extends DynamicMBean>> mbeanInterfaces() {
+ return Collections.emptySet(); // DynamicMBean cannot be used to find an MBean by ManagementFactory
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return e.getKey().getCanonicalName();
+ }
+
+ @Override
+ public Map<String, DynamicMBean> nameToMBeanMap() {
+ return Collections.<String, DynamicMBean>singletonMap(
+ e.getKey().getCanonicalName(),
+ e.getValue());
+ }
+ });
+ }
+ initMBeanList.trimToSize();
+ return initMBeanList;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/java/lang/management/DefaultPlatformMBeanProvider.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,503 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package java.lang.management;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.management.DynamicMBean;
+import javax.management.ObjectName;
+import sun.management.ManagementFactoryHelper;
+import sun.management.spi.PlatformMBeanProvider;
+
+class DefaultPlatformMBeanProvider extends PlatformMBeanProvider {
+ private final List<PlatformComponent<?>> mxbeanList;
+
+ DefaultPlatformMBeanProvider() {
+ mxbeanList = Collections.unmodifiableList(init());
+ }
+
+ @Override
+ public List<PlatformComponent<?>> getPlatformComponentList() {
+ return mxbeanList;
+ }
+
+ private List<PlatformComponent<?>> init() {
+ ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>();
+ /**
+ * Class loading system of the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<ClassLoadingMXBean>() {
+ private final Set<String> classLoadingInterfaceNames =
+ Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.ClassLoadingMXBean"));
+
+ @Override
+ public Set<Class<? extends ClassLoadingMXBean>> mbeanInterfaces() {
+ return Collections.singleton(ClassLoadingMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return classLoadingInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.CLASS_LOADING_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, ClassLoadingMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ ManagementFactory.CLASS_LOADING_MXBEAN_NAME,
+ ManagementFactoryHelper.getClassLoadingMXBean());
+ }
+ });
+
+ /**
+ * Compilation system of the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<CompilationMXBean>() {
+ private final Set<String> compilationMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.CompilationMXBean"));
+
+ @Override
+ public Set<Class<? extends CompilationMXBean>> mbeanInterfaces() {
+ return Collections.singleton(CompilationMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return compilationMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.COMPILATION_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, CompilationMXBean> nameToMBeanMap() {
+ CompilationMXBean m = ManagementFactoryHelper.getCompilationMXBean();
+ if (m == null) {
+ return Collections.emptyMap();
+ } else {
+ return Collections.singletonMap(
+ ManagementFactory.COMPILATION_MXBEAN_NAME,
+ ManagementFactoryHelper.getCompilationMXBean());
+ }
+ }
+ });
+
+ /**
+ * Memory system of the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<MemoryMXBean>() {
+ private final Set<String> memoryMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.MemoryMXBean"));
+
+ @Override
+ public Set<Class<? extends MemoryMXBean>> mbeanInterfaces() {
+ return Collections.singleton(MemoryMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return memoryMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.MEMORY_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, MemoryMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ ManagementFactory.MEMORY_MXBEAN_NAME,
+ ManagementFactoryHelper.getMemoryMXBean());
+ }
+ });
+
+ /**
+ * Garbage Collector in the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<MemoryManagerMXBean>() {
+ private final Set<String> garbageCollectorMXBeanInterfaceNames
+ = Collections.unmodifiableSet(
+ Stream.of("java.lang.management.MemoryManagerMXBean",
+ "java.lang.management.GarbageCollectorMXBean")
+ .collect(Collectors.toSet()));
+ @Override
+ public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() {
+ return Stream.of(MemoryManagerMXBean.class,
+ GarbageCollectorMXBean.class,
+ com.sun.management.GarbageCollectorMXBean.class).collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return garbageCollectorMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*";
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false; // zero or more instances
+ }
+
+ @Override
+ public Map<String, MemoryManagerMXBean> nameToMBeanMap() {
+ List<GarbageCollectorMXBean> list
+ = ManagementFactoryHelper.getGarbageCollectorMXBeans();
+ Map<String, MemoryManagerMXBean> map;
+ if (list.isEmpty()) {
+ map = Collections.emptyMap();
+ } else {
+ map = new HashMap<>(list.size());
+ for (MemoryManagerMXBean gcm : list) {
+ map.put(gcm.getObjectName().getCanonicalName(),
+ gcm);
+ }
+ }
+ return map;
+ }
+
+ });
+
+ /**
+ * Memory manager in the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<MemoryManagerMXBean>() {
+ private final Set<String> memoryManagerMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.MemoryManagerMXBean"));
+
+ @Override
+ public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() {
+ return Collections.singleton(MemoryManagerMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return memoryManagerMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE + ",name=*";
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false; // zero or more instances
+ }
+
+ @Override
+ public Map<String, MemoryManagerMXBean> nameToMBeanMap() {
+ List<MemoryManagerMXBean> list
+ = ManagementFactoryHelper.getMemoryManagerMXBeans();
+ return list.stream()
+ .filter(this::isMemoryManager)
+ .collect(Collectors.toMap(
+ pmo -> pmo.getObjectName().getCanonicalName(), Function.identity()));
+ }
+
+ // ManagementFactoryHelper.getMemoryManagerMXBeans() returns all
+ // memory managers - we need to filter out those that do not match
+ // the pattern for which we are registered
+ private boolean isMemoryManager(MemoryManagerMXBean mbean) {
+ final ObjectName name = mbean.getObjectName();
+ return ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE.startsWith(name.getDomain())
+ && ManagementFactory.MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE.contains(
+ "type="+name.getKeyProperty("type"));
+ }
+ });
+
+ /**
+ * Memory pool in the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<MemoryPoolMXBean>() {
+ private final Set<String> memoryPoolMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.MemoryPoolMXBean"));
+
+ @Override
+ public Set<Class<? extends MemoryPoolMXBean>> mbeanInterfaces() {
+ return Collections.singleton(MemoryPoolMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return memoryPoolMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=*";
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false; // zero or more instances
+ }
+
+ @Override
+ public Map<String, MemoryPoolMXBean> nameToMBeanMap() {
+ List<MemoryPoolMXBean> list
+ = ManagementFactoryHelper.getMemoryPoolMXBeans();
+ Map<String, MemoryPoolMXBean> map;
+ if (list.isEmpty()) {
+ map = Collections.<String, MemoryPoolMXBean>emptyMap();
+ } else {
+ map = new HashMap<>(list.size());
+ for (MemoryPoolMXBean mpm : list) {
+ map.put(mpm.getObjectName().getCanonicalName(),
+ mpm);
+ }
+ }
+ return map;
+ }
+ });
+
+ /**
+ * Runtime system of the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<RuntimeMXBean>() {
+ private final Set<String> runtimeMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.RuntimeMXBean"));
+
+ @Override
+ public Set<Class<? extends RuntimeMXBean>> mbeanInterfaces() {
+ return Collections.singleton(RuntimeMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return runtimeMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.RUNTIME_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, RuntimeMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ ManagementFactory.RUNTIME_MXBEAN_NAME,
+ ManagementFactoryHelper.getRuntimeMXBean());
+ }
+ });
+
+ /**
+ * Threading system of the Java virtual machine.
+ */
+ initMBeanList.add(new PlatformComponent<ThreadMXBean>() {
+ private final Set<String> threadMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.ThreadMXBean"));
+
+ @Override
+ public Set<Class<? extends ThreadMXBean>> mbeanInterfaces() {
+ return Collections.singleton(ThreadMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return threadMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.THREAD_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, ThreadMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ ManagementFactory.THREAD_MXBEAN_NAME,
+ ManagementFactoryHelper.getThreadMXBean());
+ }
+ });
+
+ /**
+ * Logging facility.
+ */
+ initMBeanList.add(new PlatformComponent<PlatformLoggingMXBean>() {
+ private final Set<String> platformLoggingMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.PlatformLoggingMXBean"));
+
+ @Override
+ public Set<Class<? extends PlatformLoggingMXBean>> mbeanInterfaces() {
+ return Collections.singleton(PlatformLoggingMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return platformLoggingMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return "java.util.logging:type=Logging";
+ }
+
+ @Override
+ public Map<String, PlatformLoggingMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ "java.util.logging:type=Logging",
+ ManagementFactoryHelper.getPlatformLoggingMXBean());
+ }
+ });
+
+ /**
+ * Buffer pools.
+ */
+ initMBeanList.add(new PlatformComponent<BufferPoolMXBean>() {
+ private final Set<String> bufferPoolMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.BufferPoolMXBean"));
+
+ @Override
+ public Set<Class<? extends BufferPoolMXBean>> mbeanInterfaces() {
+ return Collections.singleton(BufferPoolMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return bufferPoolMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return "java.nio:type=BufferPool,name=*";
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false; // zero or more instances
+ }
+
+ @Override
+ public Map<String, BufferPoolMXBean> nameToMBeanMap() {
+ List<BufferPoolMXBean> list
+ = ManagementFactoryHelper.getBufferPoolMXBeans();
+ Map<String, BufferPoolMXBean> map;
+ if (list.isEmpty()) {
+ map = Collections.<String, BufferPoolMXBean>emptyMap();
+ } else {
+ map = new HashMap<>(list.size());
+ list.stream()
+ .forEach(mbean -> map.put(mbean.getObjectName().getCanonicalName(),mbean));
+ }
+ return map;
+ }
+ });
+
+ /**
+ * OperatingSystemMXBean
+ */
+ initMBeanList.add(new PlatformComponent<OperatingSystemMXBean>() {
+ private final Set<String> operatingSystemMXBeanInterfaceNames
+ = Collections.unmodifiableSet(Collections.singleton(
+ "java.lang.management.OperatingSystemMXBean"));
+
+ @Override
+ public Set<Class<? extends OperatingSystemMXBean>> mbeanInterfaces() {
+ return Collections.singleton(OperatingSystemMXBean.class);
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return operatingSystemMXBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME;
+ }
+
+ @Override
+ public Map<String, OperatingSystemMXBean> nameToMBeanMap() {
+ return Collections.singletonMap(
+ ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME,
+ ManagementFactoryHelper.getOperatingSystemMXBean());
+ }
+
+ });
+
+ /**
+ * DynamicMBean
+ */
+ HashMap<ObjectName, DynamicMBean> dynmbeans
+ = ManagementFactoryHelper.getPlatformDynamicMBeans();
+ final Set<String> dynamicMBeanInterfaceNames =
+ Collections.unmodifiableSet(Collections.singleton("javax.management.DynamicMBean"));
+ for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
+ initMBeanList.add(new PlatformComponent<DynamicMBean>() {
+ @Override
+ public Set<Class<? extends DynamicMBean>> mbeanInterfaces() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Set<String> mbeanInterfaceNames() {
+ return dynamicMBeanInterfaceNames;
+ }
+
+ @Override
+ public String getObjectNamePattern() {
+ return e.getKey().getCanonicalName();
+ }
+
+ @Override
+ public Map<String, DynamicMBean> nameToMBeanMap() {
+ return Collections.<String, DynamicMBean>singletonMap(
+ e.getKey().getCanonicalName(),
+ e.getValue());
+ }
+ });
+ }
+
+ initMBeanList.trimToSize();
+ return initMBeanList;
+ }
+}
--- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,35 +24,40 @@
*/
package java.lang.management;
+import java.io.FilePermission;
+import java.io.IOException;
import javax.management.DynamicMBean;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.MBeanServerPermission;
import javax.management.NotificationEmitter;
-import javax.management.ObjectInstance;
import javax.management.ObjectName;
-import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MalformedObjectNameException;
-import javax.management.MBeanRegistrationException;
-import javax.management.NotCompliantMBeanException;
import javax.management.StandardEmitterMBean;
import javax.management.StandardMBean;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import static java.util.stream.Collectors.toMap;
+import java.util.stream.Stream;
import javax.management.JMX;
-import sun.management.ManagementFactoryHelper;
-import sun.management.ExtendedPlatformComponent;
+import sun.management.Util;
+import sun.management.spi.PlatformMBeanProvider;
+import sun.management.spi.PlatformMBeanProvider.PlatformComponent;
/**
* The {@code ManagementFactory} class is a factory class for getting
@@ -316,7 +321,7 @@
* the Java virtual machine.
*/
public static ClassLoadingMXBean getClassLoadingMXBean() {
- return ManagementFactoryHelper.getClassLoadingMXBean();
+ return getPlatformMXBean(ClassLoadingMXBean.class);
}
/**
@@ -326,7 +331,7 @@
* @return a {@link MemoryMXBean} object for the Java virtual machine.
*/
public static MemoryMXBean getMemoryMXBean() {
- return ManagementFactoryHelper.getMemoryMXBean();
+ return getPlatformMXBean(MemoryMXBean.class);
}
/**
@@ -336,7 +341,7 @@
* @return a {@link ThreadMXBean} object for the Java virtual machine.
*/
public static ThreadMXBean getThreadMXBean() {
- return ManagementFactoryHelper.getThreadMXBean();
+ return getPlatformMXBean(ThreadMXBean.class);
}
/**
@@ -347,7 +352,7 @@
*/
public static RuntimeMXBean getRuntimeMXBean() {
- return ManagementFactoryHelper.getRuntimeMXBean();
+ return getPlatformMXBean(RuntimeMXBean.class);
}
/**
@@ -360,7 +365,7 @@
* no compilation system.
*/
public static CompilationMXBean getCompilationMXBean() {
- return ManagementFactoryHelper.getCompilationMXBean();
+ return getPlatformMXBean(CompilationMXBean.class);
}
/**
@@ -371,7 +376,7 @@
* the Java virtual machine.
*/
public static OperatingSystemMXBean getOperatingSystemMXBean() {
- return ManagementFactoryHelper.getOperatingSystemMXBean();
+ return getPlatformMXBean(OperatingSystemMXBean.class);
}
/**
@@ -384,7 +389,7 @@
*
*/
public static List<MemoryPoolMXBean> getMemoryPoolMXBeans() {
- return ManagementFactoryHelper.getMemoryPoolMXBeans();
+ return getPlatformMXBeans(MemoryPoolMXBean.class);
}
/**
@@ -397,7 +402,7 @@
*
*/
public static List<MemoryManagerMXBean> getMemoryManagerMXBeans() {
- return ManagementFactoryHelper.getMemoryManagerMXBeans();
+ return getPlatformMXBeans(MemoryManagerMXBean.class);
}
@@ -413,7 +418,7 @@
*
*/
public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() {
- return ManagementFactoryHelper.getGarbageCollectorMXBeans();
+ return getPlatformMXBeans(GarbageCollectorMXBean.class);
}
private static MBeanServer platformMBeanServer;
@@ -467,35 +472,11 @@
if (platformMBeanServer == null) {
platformMBeanServer = MBeanServerFactory.createMBeanServer();
- for (PlatformComponent pc : PlatformComponent.values()) {
- List<? extends PlatformManagedObject> list =
- pc.getMXBeans(pc.getMXBeanInterface());
- for (PlatformManagedObject o : list) {
- // Each PlatformComponent represents one management
- // interface. Some MXBean may extend another one.
- // The MXBean instances for one platform component
- // (returned by pc.getMXBeans()) might be also
- // the MXBean instances for another platform component.
- // e.g. com.sun.management.GarbageCollectorMXBean
- //
- // So need to check if an MXBean instance is registered
- // before registering into the platform MBeanServer
- if (!platformMBeanServer.isRegistered(o.getObjectName())) {
- addMXBean(platformMBeanServer, o);
- }
- }
- }
- HashMap<ObjectName, DynamicMBean> dynmbeans =
- ManagementFactoryHelper.getPlatformDynamicMBeans();
- for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) {
- addDynamicMBean(platformMBeanServer, e.getValue(), e.getKey());
- }
- for (final PlatformManagedObject o :
- ExtendedPlatformComponent.getMXBeans()) {
- if (!platformMBeanServer.isRegistered(o.getObjectName())) {
- addMXBean(platformMBeanServer, o);
- }
- }
+ platformComponents()
+ .stream()
+ .filter(PlatformComponent::shouldRegister)
+ .flatMap(pc -> pc.nameToMBeanMap().entrySet().stream())
+ .forEach(entry -> addMXBean(platformMBeanServer, entry.getKey(), entry.getValue()));
}
return platformMBeanServer;
}
@@ -600,11 +581,8 @@
// bootstrap class loader
final Class<?> cls = mxbeanInterface;
ClassLoader loader =
- AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
- public ClassLoader run() {
- return cls.getClassLoader();
- }
- });
+ AccessController.doPrivileged(
+ (PrivilegedAction<ClassLoader>) () -> cls.getClassLoader());
if (!sun.misc.VM.isSystemDomainLoader(loader)) {
throw new IllegalArgumentException(mxbeanName +
" is not a platform MXBean");
@@ -619,7 +597,6 @@
" is not an instance of " + mxbeanInterface);
}
- final Class<?>[] interfaces;
// check if the registered MBean is a notification emitter
boolean emitter = connection.isInstanceOf(objName, NOTIF_EMITTER);
@@ -661,20 +638,11 @@
*/
public static <T extends PlatformManagedObject>
T getPlatformMXBean(Class<T> mxbeanInterface) {
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
- if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- return mbean;
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
- }
- if (!pc.isSingleton())
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " can have zero or more than one instances");
+ PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
- return pc.getSingletonMXBean(mxbeanInterface);
+ List<? extends T> mbeans = pc.getMBeans(mxbeanInterface);
+ assert mbeans.isEmpty() || mbeans.size() == 1;
+ return mbeans.isEmpty() ? null : mbeans.get(0);
}
/**
@@ -701,16 +669,19 @@
*/
public static <T extends PlatformManagedObject> List<T>
getPlatformMXBeans(Class<T> mxbeanInterface) {
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
+ // Validates at first the specified interface by finding at least one
+ // PlatformComponent whose MXBean implements this interface.
+ // An interface can be implemented by different MBeans, provided by
+ // different platform components.
+ PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- return Collections.singletonList(mbean);
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
+ throw new IllegalArgumentException(mxbeanInterface.getName()
+ + " is not a platform management interface");
}
- return Collections.unmodifiableList(pc.getMXBeans(mxbeanInterface));
+
+ return platformComponents().stream()
+ .flatMap(p -> p.getMBeans(mxbeanInterface).stream())
+ .collect(Collectors.toList());
}
/**
@@ -753,22 +724,8 @@
Class<T> mxbeanInterface)
throws java.io.IOException
{
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
- if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- ObjectName on = mbean.getObjectName();
- return ManagementFactory.newPlatformMXBeanProxy(connection,
- on.getCanonicalName(),
- mxbeanInterface);
- }
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
- }
- if (!pc.isSingleton())
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " can have zero or more than one instances");
- return pc.getSingletonMXBean(connection, mxbeanInterface);
+ PlatformComponent<?> pc = PlatformMBeanFinder.findSingleton(mxbeanInterface);
+ return newPlatformMXBeanProxy(connection, pc.getObjectNamePattern(), mxbeanInterface);
}
/**
@@ -804,19 +761,56 @@
Class<T> mxbeanInterface)
throws java.io.IOException
{
- PlatformComponent pc = PlatformComponent.getPlatformComponent(mxbeanInterface);
+ // Validates at first the specified interface by finding at least one
+ // PlatformComponent whose MXBean implements this interface.
+ // An interface can be implemented by different MBeans, provided by
+ // different platform components.
+ PlatformComponent<?> pc = PlatformMBeanFinder.findFirst(mxbeanInterface);
if (pc == null) {
- T mbean = ExtendedPlatformComponent.getMXBean(mxbeanInterface);
- if (mbean != null) {
- ObjectName on = mbean.getObjectName();
- T proxy = ManagementFactory.newPlatformMXBeanProxy(connection,
- on.getCanonicalName(), mxbeanInterface);
- return Collections.singletonList(proxy);
+ throw new IllegalArgumentException(mxbeanInterface.getName()
+ + " is not a platform management interface");
+ }
+
+ // Collect all names, eliminate duplicates.
+ Stream<String> names = Stream.empty();
+ for (PlatformComponent<?> p : platformComponents()) {
+ names = Stream.concat(names, getProxyNames(p, connection, mxbeanInterface));
+ }
+ Set<String> objectNames = names.collect(Collectors.toSet());
+ if (objectNames.isEmpty()) return Collections.emptyList();
+
+ // Map names on proxies.
+ List<T> proxies = new ArrayList<>();
+ for (String name : objectNames) {
+ proxies.add(newPlatformMXBeanProxy(connection, name, mxbeanInterface));
+ }
+ return proxies;
+ }
+
+ // Returns a stream containing all ObjectNames of the MBeans represented by
+ // the specified PlatformComponent and implementing the specified interface.
+ // If the PlatformComponent is a singleton, the name returned by
+ // PlatformComponent.getObjectNamePattern() will be used, otherwise
+ // we will query the specified MBeanServerConnection (conn.queryNames)
+ // with the pattern returned by PlatformComponent.getObjectNamePattern()
+ // in order to find the names of matching MBeans.
+ // In case of singleton, we do not check whether the MBean is registered
+ // in the connection because the caller "getPlatformMXBeans" will do the check
+ // when creating a proxy.
+ private static Stream<String> getProxyNames(PlatformComponent<?> pc,
+ MBeanServerConnection conn,
+ Class<?> intf)
+ throws IOException
+ {
+ if (pc.mbeanInterfaceNames().contains(intf.getName())) {
+ if (pc.isSingleton()) {
+ return Stream.of(pc.getObjectNamePattern());
+ } else {
+ return conn.queryNames(Util.newObjectName(pc.getObjectNamePattern()), null)
+ .stream().map(ObjectName::getCanonicalName);
}
- throw new IllegalArgumentException(mxbeanInterface.getName() +
- " is not a platform management interface");
}
- return Collections.unmodifiableList(pc.getMXBeans(connection, mxbeanInterface));
+ return Stream.empty();
}
/**
@@ -835,63 +829,145 @@
public static Set<Class<? extends PlatformManagedObject>>
getPlatformManagementInterfaces()
{
- Set<Class<? extends PlatformManagedObject>> result =
- new HashSet<>();
- for (PlatformComponent component: PlatformComponent.values()) {
- result.add(component.getMXBeanInterface());
- }
- return Collections.unmodifiableSet(result);
+ return platformComponents()
+ .stream()
+ .flatMap(pc -> pc.mbeanInterfaces().stream())
+ .filter(clazz -> PlatformManagedObject.class.isAssignableFrom(clazz))
+ .map(clazz -> clazz.asSubclass(PlatformManagedObject.class))
+ .collect(Collectors.toSet());
}
private static final String NOTIF_EMITTER =
"javax.management.NotificationEmitter";
- /**
- * Registers an MXBean.
- */
- private static void addMXBean(final MBeanServer mbs, final PlatformManagedObject pmo) {
- // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
+ private static void addMXBean(final MBeanServer mbs, String name, final Object pmo)
+ {
try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- public Void run() throws InstanceAlreadyExistsException,
- MBeanRegistrationException,
- NotCompliantMBeanException {
- final DynamicMBean dmbean;
- if (pmo instanceof DynamicMBean) {
- dmbean = DynamicMBean.class.cast(pmo);
- } else if (pmo instanceof NotificationEmitter) {
- dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
- } else {
- dmbean = new StandardMBean(pmo, null, true);
- }
+ ObjectName oname = ObjectName.getInstance(name);
+ // Make DynamicMBean out of MXBean by wrapping it with a StandardMBean
+ AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
+ final DynamicMBean dmbean;
+ if (pmo instanceof DynamicMBean) {
+ dmbean = DynamicMBean.class.cast(pmo);
+ } else if (pmo instanceof NotificationEmitter) {
+ dmbean = new StandardEmitterMBean(pmo, null, true, (NotificationEmitter) pmo);
+ } else {
+ dmbean = new StandardMBean(pmo, null, true);
+ }
- mbs.registerMBean(dmbean, pmo.getObjectName());
- return null;
- }
+ mbs.registerMBean(dmbean, oname);
+ return null;
});
+ } catch (MalformedObjectNameException mone) {
+ throw new IllegalArgumentException(mone);
} catch (PrivilegedActionException e) {
throw new RuntimeException(e.getException());
}
}
- /**
- * Registers a DynamicMBean.
- */
- private static void addDynamicMBean(final MBeanServer mbs,
- final DynamicMBean dmbean,
- final ObjectName on) {
- try {
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws InstanceAlreadyExistsException,
- MBeanRegistrationException,
- NotCompliantMBeanException {
- mbs.registerMBean(dmbean, on);
- return null;
- }
- });
- } catch (PrivilegedActionException e) {
- throw new RuntimeException(e.getException());
+ private static Collection<PlatformComponent<?>> platformComponents()
+ {
+ return PlatformMBeanFinder.getMap().values();
+ }
+
+ private static class PlatformMBeanFinder
+ {
+ private static final Map<String, PlatformComponent<?>> componentMap;
+ static {
+ // get all providers
+ List<PlatformMBeanProvider> providers = AccessController.doPrivileged(
+ (PrivilegedAction<List<PlatformMBeanProvider>>) () -> {
+ List<PlatformMBeanProvider> all = new ArrayList<>();
+ ServiceLoader.loadInstalled(PlatformMBeanProvider.class)
+ .forEach(all::add);
+ all.add(new DefaultPlatformMBeanProvider());
+ return all;
+ }, null, new FilePermission("<<ALL FILES>>", "read"),
+ new RuntimePermission("sun.management.spi.PlatformMBeanProvider"));
+
+ // load all platform components into a map
+ componentMap = providers.stream()
+ .flatMap(p -> toPlatformComponentStream(p))
+ // The first one wins if multiple PlatformComponents
+ // with same ObjectName pattern,
+ .collect(toMap(PlatformComponent::getObjectNamePattern,
+ Function.identity(),
+ (p1, p2) -> p1));
+ }
+
+ static Map<String, PlatformComponent<?>> getMap() {
+ return componentMap;
+ }
+
+ // Loads all platform components from a provider into a stream
+ // Ensures that two different components are not declared with the same
+ // object name pattern. Throws InternalError if the provider incorrectly
+ // declares two platform components with the same pattern.
+ private static Stream<PlatformComponent<?>>
+ toPlatformComponentStream(PlatformMBeanProvider provider)
+ {
+ return provider.getPlatformComponentList()
+ .stream()
+ .collect(toMap(PlatformComponent::getObjectNamePattern,
+ Function.identity(),
+ (p1, p2) -> {
+ throw new InternalError(
+ p1.getObjectNamePattern() +
+ " has been used as key for " + p1 +
+ ", it cannot be reused for " + p2);
+ }))
+ .values().stream();
+ }
+
+ // Finds the first PlatformComponent whose mbeanInterfaceNames() list
+ // contains the specified class name. An MBean interface can be implemented
+ // by different MBeans, provided by different platform components.
+ // For instance the MemoryManagerMXBean interface is implemented both by
+ // regular memory managers, and garbage collector MXBeans. This method is
+ // mainly used to verify that there is at least one PlatformComponent
+ // which provides an implementation of the desired interface.
+ static PlatformComponent<?> findFirst(Class<?> mbeanIntf)
+ {
+ String name = mbeanIntf.getName();
+ Optional<PlatformComponent<?>> op = getMap().values()
+ .stream()
+ .filter(pc -> pc.mbeanInterfaceNames().contains(name))
+ .findFirst();
+
+ if (op.isPresent()) {
+ return op.get();
+ } else {
+ return null;
+ }
+ }
+
+ // Finds a PlatformComponent whose mbeanInterface name list contains
+ // the specified class name, and make sure that one and only one exists.
+ static PlatformComponent<?> findSingleton(Class<?> mbeanIntf)
+ {
+ String name = mbeanIntf.getName();
+ Optional<PlatformComponent<?>> op = getMap().values()
+ .stream()
+ .filter(pc -> pc.mbeanInterfaceNames().contains(name))
+ .reduce((p1, p2) -> {
+ if (p2 != null) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " can have more than one instance");
+ } else {
+ return p1;
+ }
+ });
+
+ PlatformComponent<?> singleton = op.isPresent() ? op.get() : null;
+ if (singleton == null) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " is not a platform management interface");
+ }
+ if (!singleton.isSingleton()) {
+ throw new IllegalArgumentException(mbeanIntf.getName() +
+ " can have more than one instance");
+ }
+ return singleton;
}
}
}
--- a/jdk/src/java.management/share/classes/java/lang/management/PlatformComponent.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,468 +0,0 @@
-/*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.management;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import javax.management.MBeanServerConnection;
-import javax.management.ObjectName;
-
-import com.sun.management.HotSpotDiagnosticMXBean;
-import com.sun.management.UnixOperatingSystemMXBean;
-
-import sun.management.ManagementFactoryHelper;
-import sun.management.Util;
-
-/**
- * This enum class defines the list of platform components
- * that provides monitoring and management support.
- * Each enum represents one MXBean interface. A MXBean
- * instance could implement one or more MXBean interfaces.
- *
- * For example, com.sun.management.GarbageCollectorMXBean
- * extends java.lang.management.GarbageCollectorMXBean
- * and there is one set of garbage collection MXBean instances,
- * each of which implements both c.s.m. and j.l.m. interfaces.
- * There are two separate enums GARBAGE_COLLECTOR
- * and SUN_GARBAGE_COLLECTOR so that ManagementFactory.getPlatformMXBeans(Class)
- * will return the list of MXBeans of the specified type.
- *
- * To add a new MXBean interface for the Java platform,
- * add a new enum constant and implement the MXBeanFetcher.
- */
-enum PlatformComponent {
-
- /**
- * Class loading system of the Java virtual machine.
- */
- CLASS_LOADING(
- "java.lang.management.ClassLoadingMXBean",
- "java.lang", "ClassLoading", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<ClassLoadingMXBean>() {
- public List<ClassLoadingMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getClassLoadingMXBean());
- }
- }),
-
- /**
- * Compilation system of the Java virtual machine.
- */
- COMPILATION(
- "java.lang.management.CompilationMXBean",
- "java.lang", "Compilation", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<CompilationMXBean>() {
- public List<CompilationMXBean> getMXBeans() {
- CompilationMXBean m = ManagementFactoryHelper.getCompilationMXBean();
- if (m == null) {
- return Collections.emptyList();
- } else {
- return Collections.singletonList(m);
- }
- }
- }),
-
- /**
- * Memory system of the Java virtual machine.
- */
- MEMORY(
- "java.lang.management.MemoryMXBean",
- "java.lang", "Memory", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<MemoryMXBean>() {
- public List<MemoryMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getMemoryMXBean());
- }
- }),
-
- /**
- * Garbage Collector in the Java virtual machine.
- */
- GARBAGE_COLLECTOR(
- "java.lang.management.GarbageCollectorMXBean",
- "java.lang", "GarbageCollector", keyProperties("name"),
- false, // zero or more instances
- new MXBeanFetcher<GarbageCollectorMXBean>() {
- public List<GarbageCollectorMXBean> getMXBeans() {
- return ManagementFactoryHelper.
- getGarbageCollectorMXBeans();
- }
- }),
-
- /**
- * Memory manager in the Java virtual machine.
- */
- MEMORY_MANAGER(
- "java.lang.management.MemoryManagerMXBean",
- "java.lang", "MemoryManager", keyProperties("name"),
- false, // zero or more instances
- new MXBeanFetcher<MemoryManagerMXBean>() {
- public List<MemoryManagerMXBean> getMXBeans() {
- return ManagementFactoryHelper.getMemoryManagerMXBeans();
- }
- },
- GARBAGE_COLLECTOR),
-
- /**
- * Memory pool in the Java virtual machine.
- */
- MEMORY_POOL(
- "java.lang.management.MemoryPoolMXBean",
- "java.lang", "MemoryPool", keyProperties("name"),
- false, // zero or more instances
- new MXBeanFetcher<MemoryPoolMXBean>() {
- public List<MemoryPoolMXBean> getMXBeans() {
- return ManagementFactoryHelper.getMemoryPoolMXBeans();
- }
- }),
-
- /**
- * Operating system on which the Java virtual machine is running
- */
- OPERATING_SYSTEM(
- "java.lang.management.OperatingSystemMXBean",
- "java.lang", "OperatingSystem", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<OperatingSystemMXBean>() {
- public List<OperatingSystemMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getOperatingSystemMXBean());
- }
- }),
-
- /**
- * Runtime system of the Java virtual machine.
- */
- RUNTIME(
- "java.lang.management.RuntimeMXBean",
- "java.lang", "Runtime", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<RuntimeMXBean>() {
- public List<RuntimeMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getRuntimeMXBean());
- }
- }),
-
- /**
- * Threading system of the Java virtual machine.
- */
- THREADING(
- "java.lang.management.ThreadMXBean",
- "java.lang", "Threading", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<ThreadMXBean>() {
- public List<ThreadMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getThreadMXBean());
- }
- }),
-
-
- /**
- * Logging facility.
- */
- LOGGING(
- "java.lang.management.PlatformLoggingMXBean",
- "java.util.logging", "Logging", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<PlatformLoggingMXBean>() {
- public List<PlatformLoggingMXBean> getMXBeans() {
- PlatformLoggingMXBean m = ManagementFactoryHelper.getPlatformLoggingMXBean();
- if (m == null) {
- return Collections.emptyList();
- } else {
- return Collections.singletonList(m);
- }
- }
- }),
-
- /**
- * Buffer pools.
- */
- BUFFER_POOL(
- "java.lang.management.BufferPoolMXBean",
- "java.nio", "BufferPool", keyProperties("name"),
- false, // zero or more instances
- new MXBeanFetcher<BufferPoolMXBean>() {
- public List<BufferPoolMXBean> getMXBeans() {
- return ManagementFactoryHelper.getBufferPoolMXBeans();
- }
- }),
-
-
- // Sun Platform Extension
-
- /**
- * Sun extension garbage collector that performs collections in cycles.
- */
- SUN_GARBAGE_COLLECTOR(
- "com.sun.management.GarbageCollectorMXBean",
- "java.lang", "GarbageCollector", keyProperties("name"),
- false, // zero or more instances
- new MXBeanFetcher<com.sun.management.GarbageCollectorMXBean>() {
- public List<com.sun.management.GarbageCollectorMXBean> getMXBeans() {
- return getGcMXBeanList(com.sun.management.GarbageCollectorMXBean.class);
- }
- }),
-
- /**
- * Sun extension operating system on which the Java virtual machine
- * is running.
- */
- SUN_OPERATING_SYSTEM(
- "com.sun.management.OperatingSystemMXBean",
- "java.lang", "OperatingSystem", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<com.sun.management.OperatingSystemMXBean>() {
- public List<com.sun.management.OperatingSystemMXBean> getMXBeans() {
- return getOSMXBeanList(com.sun.management.OperatingSystemMXBean.class);
- }
- }),
-
- /**
- * Unix operating system.
- */
- SUN_UNIX_OPERATING_SYSTEM(
- "com.sun.management.UnixOperatingSystemMXBean",
- "java.lang", "OperatingSystem", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<UnixOperatingSystemMXBean>() {
- public List<UnixOperatingSystemMXBean> getMXBeans() {
- return getOSMXBeanList(com.sun.management.UnixOperatingSystemMXBean.class);
- }
- }),
-
- /**
- * Diagnostic support for the HotSpot Virtual Machine.
- */
- HOTSPOT_DIAGNOSTIC(
- "com.sun.management.HotSpotDiagnosticMXBean",
- "com.sun.management", "HotSpotDiagnostic", defaultKeyProperties(),
- true, // singleton
- new MXBeanFetcher<HotSpotDiagnosticMXBean>() {
- public List<HotSpotDiagnosticMXBean> getMXBeans() {
- return Collections.singletonList(ManagementFactoryHelper.getDiagnosticMXBean());
- }
- });
-
-
- /**
- * A task that returns the MXBeans for a component.
- */
- interface MXBeanFetcher<T extends PlatformManagedObject> {
- public List<T> getMXBeans();
- }
-
- /*
- * Returns a list of the GC MXBeans of the given type.
- */
- private static <T extends GarbageCollectorMXBean>
- List<T> getGcMXBeanList(Class<T> gcMXBeanIntf) {
- List<GarbageCollectorMXBean> list =
- ManagementFactoryHelper.getGarbageCollectorMXBeans();
- List<T> result = new ArrayList<>(list.size());
- for (GarbageCollectorMXBean m : list) {
- if (gcMXBeanIntf.isInstance(m)) {
- result.add(gcMXBeanIntf.cast(m));
- }
- }
- return result;
- }
-
- /*
- * Returns the OS mxbean instance of the given type.
- */
- private static <T extends OperatingSystemMXBean>
- List<T> getOSMXBeanList(Class<T> osMXBeanIntf) {
- OperatingSystemMXBean m =
- ManagementFactoryHelper.getOperatingSystemMXBean();
- if (osMXBeanIntf.isInstance(m)) {
- return Collections.singletonList(osMXBeanIntf.cast(m));
- } else {
- return Collections.emptyList();
- }
- }
-
- private final String mxbeanInterfaceName;
- private final String domain;
- private final String type;
- private final Set<String> keyProperties;
- private final MXBeanFetcher<?> fetcher;
- private final PlatformComponent[] subComponents;
- private final boolean singleton;
-
- private PlatformComponent(String intfName,
- String domain, String type,
- Set<String> keyProperties,
- boolean singleton,
- MXBeanFetcher<?> fetcher,
- PlatformComponent... subComponents) {
- this.mxbeanInterfaceName = intfName;
- this.domain = domain;
- this.type = type;
- this.keyProperties = keyProperties;
- this.singleton = singleton;
- this.fetcher = fetcher;
- this.subComponents = subComponents;
- }
-
- private static Set<String> defaultKeyProps;
- private static Set<String> defaultKeyProperties() {
- if (defaultKeyProps == null) {
- defaultKeyProps = Collections.singleton("type");
- }
- return defaultKeyProps;
- }
-
- private static Set<String> keyProperties(String... keyNames) {
- Set<String> set = new HashSet<>();
- set.add("type");
- for (String s : keyNames) {
- set.add(s);
- }
- return set;
- }
-
- boolean isSingleton() {
- return singleton;
- }
-
- String getMXBeanInterfaceName() {
- return mxbeanInterfaceName;
- }
-
- @SuppressWarnings("unchecked")
- Class<? extends PlatformManagedObject> getMXBeanInterface() {
- try {
- // Lazy loading the MXBean interface only when it is needed
- return (Class<? extends PlatformManagedObject>)
- Class.forName(mxbeanInterfaceName, false,
- PlatformManagedObject.class.getClassLoader());
- } catch (ClassNotFoundException x) {
- throw new AssertionError(x);
- }
- }
-
- @SuppressWarnings("unchecked")
- <T extends PlatformManagedObject>
- List<T> getMXBeans(Class<T> mxbeanInterface)
- {
- return (List<T>) fetcher.getMXBeans();
- }
-
- <T extends PlatformManagedObject> T getSingletonMXBean(Class<T> mxbeanInterface)
- {
- if (!singleton)
- throw new IllegalArgumentException(mxbeanInterfaceName +
- " can have zero or more than one instances");
-
- List<T> list = getMXBeans(mxbeanInterface);
- assert list.size() == 1;
- return list.isEmpty() ? null : list.get(0);
- }
-
- <T extends PlatformManagedObject>
- T getSingletonMXBean(MBeanServerConnection mbs, Class<T> mxbeanInterface)
- throws java.io.IOException
- {
- if (!singleton)
- throw new IllegalArgumentException(mxbeanInterfaceName +
- " can have zero or more than one instances");
-
- // ObjectName of a singleton MXBean contains only domain and type
- assert keyProperties.size() == 1;
- String on = domain + ":type=" + type;
- return ManagementFactory.newPlatformMXBeanProxy(mbs,
- on,
- mxbeanInterface);
- }
-
- <T extends PlatformManagedObject>
- List<T> getMXBeans(MBeanServerConnection mbs, Class<T> mxbeanInterface)
- throws java.io.IOException
- {
- List<T> result = new ArrayList<>();
- for (ObjectName on : getObjectNames(mbs)) {
- result.add(ManagementFactory.
- newPlatformMXBeanProxy(mbs,
- on.getCanonicalName(),
- mxbeanInterface)
- );
- }
- return result;
- }
-
- private Set<ObjectName> getObjectNames(MBeanServerConnection mbs)
- throws java.io.IOException
- {
- String domainAndType = domain + ":type=" + type;
- if (keyProperties.size() > 1) {
- // if there are more than 1 key properties (i.e. other than "type")
- domainAndType += ",*";
- }
- ObjectName on = Util.newObjectName(domainAndType);
- Set<ObjectName> set = mbs.queryNames(on, null);
- for (PlatformComponent pc : subComponents) {
- set.addAll(pc.getObjectNames(mbs));
- }
- return set;
- }
-
- // a map from MXBean interface name to PlatformComponent
- private static Map<String, PlatformComponent> enumMap;
- private static synchronized void ensureInitialized() {
- if (enumMap == null) {
- enumMap = new HashMap<>();
- for (PlatformComponent pc: PlatformComponent.values()) {
- // Use String as the key rather than Class<?> to avoid
- // causing unnecessary class loading of management interface
- enumMap.put(pc.getMXBeanInterfaceName(), pc);
- }
- }
- }
-
- static boolean isPlatformMXBean(String cn) {
- ensureInitialized();
- return enumMap.containsKey(cn);
- }
-
- static <T extends PlatformManagedObject>
- PlatformComponent getPlatformComponent(Class<T> mxbeanInterface)
- {
- ensureInitialized();
- String cn = mxbeanInterface.getName();
- PlatformComponent pc = enumMap.get(cn);
- if (pc != null && pc.getMXBeanInterface() == mxbeanInterface)
- return pc;
- return null;
- }
-
- private static final long serialVersionUID = 6992337162326171013L;
-}
--- a/jdk/src/java.management/share/classes/sun/management/ExtendedPlatformComponent.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.management;
-
-import java.util.Collections;
-import java.util.List;
-import java.lang.management.PlatformManagedObject;
-
-/**
- * Class to allow for an extended set of platform MXBeans
- */
-public final class ExtendedPlatformComponent {
- private ExtendedPlatformComponent() {} // Don't create any instances
-
- /**
- * Get the extended set of platform MXBeans that should be registered in the
- * platform MBeanServer, or an empty list if there are no such MXBeans.
- */
- public static List<? extends PlatformManagedObject> getMXBeans() {
- return Collections.emptyList();
- }
-
- /**
- * Returns the extended platform MXBean implementing the given
- * mxbeanInterface, or null if there is no such MXBean.
- */
- public static <T extends PlatformManagedObject>
- T getMXBean(Class<T> mxbeanInterface) {
- return null;
- }
-}
--- a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Mon Feb 09 09:52:48 2015 -0800
@@ -42,14 +42,11 @@
import sun.util.logging.LoggingSupport;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import com.sun.management.DiagnosticCommandMBean;
import com.sun.management.HotSpotDiagnosticMXBean;
-import static java.lang.management.ManagementFactory.*;
-
/**
* ManagementFactoryHelper provides static factory methods to create
* instances of the management interface.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.management.spi;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * The PlatformMBeanProvider class defines the abstract service interface
+ * that the {@link java.lang.management.ManagementFactory} will invoke to find,
+ * load, and register Platform MBeans.
+ *
+ * ManagementFactory loads the {@linkplain ServiceLoader#loadInstalled(java.lang.Class)
+ * installed providers} of this service interface and each provides the
+ * {@linkplain PlatformComponent platform components} that defines MXBean
+ * or DynamicMBean to be registered in the platform MBeanServer.
+ *
+ * A {@code PlatformMBeanProvider} will implement the {@code getPlatformComponentList()}
+ * method to return the list of {@code PlatformComponents} it provides.
+ */
+public abstract class PlatformMBeanProvider {
+ /**
+ * {@code PlatformComponent} models MBeans of a management interface supported
+ * by the platform.
+ *
+ * If a PlatformComponent models a singleton MBean, the {@link #getObjectNamePattern()
+ * ObjectName pattern} must be the {@link
+ * javax.management.ObjectName#getCanonicalName() canonical name} of that
+ * singleton MBean. Otherwise, it must be an ObjectName pattern
+ * that can be used to query the MBeans for this
+ * PlatformComponent registered in a {@code MBeanServer}.
+ * <br>
+ * The {@link #getObjectNamePattern() ObjectName pattern} serves as a unique
+ * key for identifying the instance of PlatformComponent. It is thus illegal
+ * for a given {@link PlatformMBeanProvider} to export several instance of
+ * PlatformComponent with the same
+ * {@link #getObjectNamePattern() ObjectName pattern} string.
+ * <br>
+ * If two different provider instances export a PlatformComponent for the
+ * same ObjectName pattern, only the PlatformComponent instance of the first
+ * provider will be taken into account.
+ *
+ * @param <T> The higher level interface for which the MBeans modeled by
+ * this object should be recognized. For instance, for the {@link
+ * java.lang.management.ManagementFactory#getOperatingSystemMXBean()
+ * Operating System MXBean}, this should be {@link
+ * java.lang.management.OperatingSystemMXBean
+ * java.lang.management.OperatingSystemMXBean}.
+ */
+ public interface PlatformComponent<T> {
+ /**
+ * Returns the names of the management interfaces implemented by the
+ * MBeans modeled by this {@code PlatformComponent}.
+ *
+ * @implNote
+ * When {@link java.lang.management.ManagementFactory#getPlatformMXBean(java.lang.Class)
+ * ManagementFactory.getPlatformMXBean(mxbeanInterface)} or {@link
+ * java.lang.management.ManagementFactory#getPlatformMXBeans(java.lang.Class)
+ * ManagementFactory.getPlatformMXBeans(mxbeanInterface)} are invoked,
+ * this PlatformComponent instance will match only if the name of the
+ * given {@code mxbeanInterface} is found in this list.
+ *
+ * @return the names of the management interfaces exported by the MBeans
+ * modeled by this object.
+ */
+ public Set<String> mbeanInterfaceNames();
+
+ /**
+ * A map from ObjectName string to the MBean instance this
+ * {@code PlatformComponent} creates.
+ *
+ * @implNote
+ * If {@link #shouldRegister()} is {@code true}, this method
+ * will be called when the {@link java.lang.management.ManagementFactory
+ * #getPlatformMBeanServer() Platform MBeanServer} is initialized.
+ * By default, this method will also be called by {@link
+ * #getMBeans(java.lang.Class)}, when {@link
+ * java.lang.management.ManagementFactory#getPlatformMXBean(java.lang.Class)
+ * ManagementFactory.getPlatformMXBean(mxbeanInterface)} or {@link
+ * java.lang.management.ManagementFactory#getPlatformMXBeans(java.lang.Class)
+ * ManagementFactory.getPlatformMXBeans(mxbeanInterface)} are invoked,
+ * and when the name of the given {@code mxbeanInterface} is contained
+ * in the names of management interfaces returned by {@link
+ * #mbeanInterfaceNames()}.
+ *
+ * @return A map with, for each MBean, the ObjectName string as key
+ * and the MBean as value.
+ */
+ public Map<String, T> nameToMBeanMap();
+
+ /**
+ * An ObjectName pattern uniquely identifies the MBeans
+ * modeled by this {@code PlatformComponent}.
+ * If this instance models a singleton MBean, this must be
+ * the {@link
+ * javax.management.ObjectName#getCanonicalName() canonical name}
+ * of that singleton MBean.
+ *
+ * @return An ObjectName pattern uniquely identifies the MBeans
+ * modeled by this instance.
+ */
+ public String getObjectNamePattern();
+
+ /**
+ * Returns {@code true} if this {@code PlatformComponent} models
+ * a singleton MBean. By default, {@code true} is assumed.
+ *
+ * @return {@code true} if this instance models a singleton MBean.
+ */
+ public default boolean isSingleton() {
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the MBeans modeled by this {@code PlatformComponent}
+ * should automatically be registered in the {@link
+ * java.lang.management.ManagementFactory#getPlatformMBeanServer()
+ * Platform MBeanServer}. By default, {@code true} is assumed.
+ *
+ * @return {@code true} if the MBeans modeled by this instance should
+ * automatically be registered in the Platform MBeanServer.
+ */
+ public default boolean shouldRegister() {
+ return true;
+ }
+
+ /**
+ * The set of interfaces implemented by the MBeans modeled
+ * by this {@code PlatformComponent}.
+ *
+ * @implNote
+ * {@link java.lang.management.ManagementFactory#getPlatformManagementInterfaces()
+ * ManagementFactory.getPlatformManagementInterfaces()} calls this
+ * method to find the management interfaces supported by the platform.
+ *
+ * @return The set of interfaces implemented by the MBeans modeled
+ * by this instance
+ */
+ public Set<Class<? extends T>> mbeanInterfaces();
+
+ /**
+ * Return the list of MBeans that implement the given {@code mbeanIntf}
+ * modeled by this {@code PlatformComponent}. This method returns an
+ * empty list if no MBean implements the given {@code mbeanIntf}.
+ *
+ * @implNote This method will be called when {@link
+ * java.lang.management.ManagementFactory#getPlatformMXBean(java.lang.Class)
+ * ManagementFactory.getPlatformMXBean(mbeanIntf)} or {@link
+ * java.lang.management.ManagementFactory#getPlatformMXBeans(java.lang.Class)
+ * ManagementFactory.getPlatformMXBeans(mbeanIntf)} are invoked.
+ * By default it first checks whether the specified {@code mbeanIntf}
+ * name is contained in the returned list from the {@link #mbeanInterfaceNames()}
+ * method. If yes, it proceeds and calls
+ * {@link #mbeans().values()} and filters out all
+ * MBeans which are not instances of the given {@code mbeanIntf}.
+ * Otherwise, it returns an empty list.
+ *
+ * @param mbeanIntf A management interface.
+ * @return A (possibly empty) list of MBeans implementing the given
+ * {@code mbeanIntf}.
+ */
+ public default <I> List<? extends I> getMBeans(Class<I> mbeanIntf) {
+ List<I> list;
+
+ if (!mbeanInterfaceNames().contains(mbeanIntf.getName())) {
+ list = Collections.emptyList();
+ } else {
+ list = nameToMBeanMap().values().stream()
+ .filter(mbeanIntf::isInstance)
+ .map(mbeanIntf::cast)
+ .collect(Collectors.toList());
+ }
+ return list;
+ }
+ }
+
+ /**
+ * Instantiates a new PlatformMBeanProvider.
+ *
+ * @throws SecurityException if the subclass (and calling code) does not
+ * have {@code RuntimePermission("sun.management.spi.PlatformMBeanProvider", "subclass")}
+ */
+ protected PlatformMBeanProvider () {
+ this(checkSubclassPermission());
+ }
+
+ private PlatformMBeanProvider(Void unused) {
+ }
+
+ /**
+ * Returns a list of PlatformComponent instances describing the Platform
+ * MBeans provided by this provider.
+ *
+ * @return a list of PlatformComponent instances describing the Platform
+ * MBeans provided by this provider.
+ */
+ public abstract List<PlatformComponent<?>> getPlatformComponentList();
+
+ private static Void checkSubclassPermission() {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null) {
+ sm.checkPermission(new RuntimePermission(PlatformMBeanProvider.class.getName(), "subclass"));
+ }
+ return null;
+ }
+}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/Acl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.security.acl;
-
-import java.util.Enumeration;
-import java.security.Principal;
-
-/**
- * Interface representing an Access Control List (ACL). An Access
- * Control List is a data structure used to guard access to
- * resources.<p>
- *
- * An ACL can be thought of as a data structure with multiple ACL
- * entries. Each ACL entry, of interface type AclEntry, contains a
- * set of permissions associated with a particular principal. (A
- * principal represents an entity such as an individual user or a
- * group). Additionally, each ACL entry is specified as being either
- * positive or negative. If positive, the permissions are to be
- * granted to the associated principal. If negative, the permissions
- * are to be denied.<p>
- *
- * The ACL Entries in each ACL observe the following rules:
- *
- * <ul> <li>Each principal can have at most one positive ACL entry and
- * one negative entry; that is, multiple positive or negative ACL
- * entries are not allowed for any principal. Each entry specifies
- * the set of permissions that are to be granted (if positive) or
- * denied (if negative).
- *
- * <li>If there is no entry for a particular principal, then the
- * principal is considered to have a null (empty) permission set.
- *
- * <li>If there is a positive entry that grants a principal a
- * particular permission, and a negative entry that denies the
- * principal the same permission, the result is as though the
- * permission was never granted or denied.
- *
- * <li>Individual permissions always override permissions of the
- * group(s) to which the individual belongs. That is, individual
- * negative permissions (specific denial of permissions) override the
- * groups' positive permissions. And individual positive permissions
- * override the groups' negative permissions.
- *
- * </ul>
- *
- * The {@code java.security.acl } package provides the
- * interfaces to the ACL and related data structures (ACL entries,
- * groups, permissions, etc.), and the {@code sun.security.acl }
- * classes provide a default implementation of the interfaces. For
- * example, {@code java.security.acl.Acl } provides the
- * interface to an ACL and the {@code sun.security.acl.AclImpl }
- * class provides the default implementation of the interface.<p>
- *
- * The {@code java.security.acl.Acl } interface extends the
- * {@code java.security.acl.Owner } interface. The Owner
- * interface is used to maintain a list of owners for each ACL. Only
- * owners are allowed to modify an ACL. For example, only an owner can
- * call the ACL's {@code addEntry} method to add a new ACL entry
- * to the ACL.
- *
- * @see java.security.acl.AclEntry
- * @see java.security.acl.Owner
- * @see java.security.acl.Acl#getPermissions
- *
- * @author Satish Dharmaraj
- */
-
-public interface Acl extends Owner {
-
- /**
- * Sets the name of this ACL.
- *
- * @param caller the principal invoking this method. It must be an
- * owner of this ACL.
- *
- * @param name the name to be given to this ACL.
- *
- * @exception NotOwnerException if the caller principal
- * is not an owner of this ACL.
- *
- * @see #getName
- */
- public void setName(Principal caller, String name)
- throws NotOwnerException;
-
- /**
- * Returns the name of this ACL.
- *
- * @return the name of this ACL.
- *
- * @see #setName
- */
- public String getName();
-
- /**
- * Adds an ACL entry to this ACL. An entry associates a principal
- * (e.g., an individual or a group) with a set of
- * permissions. Each principal can have at most one positive ACL
- * entry (specifying permissions to be granted to the principal)
- * and one negative ACL entry (specifying permissions to be
- * denied). If there is already an ACL entry of the same type
- * (negative or positive) already in the ACL, false is returned.
- *
- * @param caller the principal invoking this method. It must be an
- * owner of this ACL.
- *
- * @param entry the ACL entry to be added to this ACL.
- *
- * @return true on success, false if an entry of the same type
- * (positive or negative) for the same principal is already
- * present in this ACL.
- *
- * @exception NotOwnerException if the caller principal
- * is not an owner of this ACL.
- */
- public boolean addEntry(Principal caller, AclEntry entry)
- throws NotOwnerException;
-
- /**
- * Removes an ACL entry from this ACL.
- *
- * @param caller the principal invoking this method. It must be an
- * owner of this ACL.
- *
- * @param entry the ACL entry to be removed from this ACL.
- *
- * @return true on success, false if the entry is not part of this ACL.
- *
- * @exception NotOwnerException if the caller principal is not
- * an owner of this Acl.
- */
- public boolean removeEntry(Principal caller, AclEntry entry)
- throws NotOwnerException;
-
- /**
- * Returns an enumeration for the set of allowed permissions for the
- * specified principal (representing an entity such as an individual or
- * a group). This set of allowed permissions is calculated as
- * follows:
- *
- * <ul>
- *
- * <li>If there is no entry in this Access Control List for the
- * specified principal, an empty permission set is returned.
- *
- * <li>Otherwise, the principal's group permission sets are determined.
- * (A principal can belong to one or more groups, where a group is a
- * group of principals, represented by the Group interface.)
- * The group positive permission set is the union of all
- * the positive permissions of each group that the principal belongs to.
- * The group negative permission set is the union of all
- * the negative permissions of each group that the principal belongs to.
- * If there is a specific permission that occurs in both
- * the positive permission set and the negative permission set,
- * it is removed from both.<p>
- *
- * The individual positive and negative permission sets are also
- * determined. The positive permission set contains the permissions
- * specified in the positive ACL entry (if any) for the principal.
- * Similarly, the negative permission set contains the permissions
- * specified in the negative ACL entry (if any) for the principal.
- * The individual positive (or negative) permission set is considered
- * to be null if there is not a positive (negative) ACL entry for the
- * principal in this ACL.<p>
- *
- * The set of permissions granted to the principal is then calculated
- * using the simple rule that individual permissions always override
- * the group permissions. That is, the principal's individual negative
- * permission set (specific denial of permissions) overrides the group
- * positive permission set, and the principal's individual positive
- * permission set overrides the group negative permission set.
- *
- * </ul>
- *
- * @param user the principal whose permission set is to be returned.
- *
- * @return the permission set specifying the permissions the principal
- * is allowed.
- */
- public Enumeration<Permission> getPermissions(Principal user);
-
- /**
- * Returns an enumeration of the entries in this ACL. Each element in
- * the enumeration is of type AclEntry.
- *
- * @return an enumeration of the entries in this ACL.
- */
- public Enumeration<AclEntry> entries();
-
- /**
- * Checks whether or not the specified principal has the specified
- * permission. If it does, true is returned, otherwise false is returned.
- *
- * More specifically, this method checks whether the passed permission
- * is a member of the allowed permission set of the specified principal.
- * The allowed permission set is determined by the same algorithm as is
- * used by the {@code getPermissions} method.
- *
- * @param principal the principal, assumed to be a valid authenticated
- * Principal.
- *
- * @param permission the permission to be checked for.
- *
- * @return true if the principal has the specified permission, false
- * otherwise.
- *
- * @see #getPermissions
- */
- public boolean checkPermission(Principal principal, Permission permission);
-
- /**
- * Returns a string representation of the
- * ACL contents.
- *
- * @return a string representation of the ACL contents.
- */
- public String toString();
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/AclEntry.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,154 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.security.acl;
-
-import java.util.Enumeration;
-import java.security.Principal;
-
-/**
- * This is the interface used for representing one entry in an Access
- * Control List (ACL).<p>
- *
- * An ACL can be thought of as a data structure with multiple ACL entry
- * objects. Each ACL entry object contains a set of permissions associated
- * with a particular principal. (A principal represents an entity such as
- * an individual user or a group). Additionally, each ACL entry is specified
- * as being either positive or negative. If positive, the permissions are
- * to be granted to the associated principal. If negative, the permissions
- * are to be denied. Each principal can have at most one positive ACL entry
- * and one negative entry; that is, multiple positive or negative ACL
- * entries are not allowed for any principal.
- *
- * Note: ACL entries are by default positive. An entry becomes a
- * negative entry only if the
- * {@link #setNegativePermissions() setNegativePermissions}
- * method is called on it.
- *
- * @see java.security.acl.Acl
- *
- * @author Satish Dharmaraj
- */
-public interface AclEntry extends Cloneable {
-
- /**
- * Specifies the principal for which permissions are granted or denied
- * by this ACL entry. If a principal was already set for this ACL entry,
- * false is returned, otherwise true is returned.
- *
- * @param user the principal to be set for this entry.
- *
- * @return true if the principal is set, false if there was
- * already a principal set for this entry.
- *
- * @see #getPrincipal
- */
- public boolean setPrincipal(Principal user);
-
- /**
- * Returns the principal for which permissions are granted or denied by
- * this ACL entry. Returns null if there is no principal set for this
- * entry yet.
- *
- * @return the principal associated with this entry.
- *
- * @see #setPrincipal
- */
- public Principal getPrincipal();
-
- /**
- * Sets this ACL entry to be a negative one. That is, the associated
- * principal (e.g., a user or a group) will be denied the permission set
- * specified in the entry.
- *
- * Note: ACL entries are by default positive. An entry becomes a
- * negative entry only if this {@code setNegativePermissions}
- * method is called on it.
- */
- public void setNegativePermissions();
-
- /**
- * Returns true if this is a negative ACL entry (one denying the
- * associated principal the set of permissions in the entry), false
- * otherwise.
- *
- * @return true if this is a negative ACL entry, false if it's not.
- */
- public boolean isNegative();
-
- /**
- * Adds the specified permission to this ACL entry. Note: An entry can
- * have multiple permissions.
- *
- * @param permission the permission to be associated with
- * the principal in this entry.
- *
- * @return true if the permission was added, false if the
- * permission was already part of this entry's permission set.
- */
- public boolean addPermission(Permission permission);
-
- /**
- * Removes the specified permission from this ACL entry.
- *
- * @param permission the permission to be removed from this entry.
- *
- * @return true if the permission is removed, false if the
- * permission was not part of this entry's permission set.
- */
- public boolean removePermission(Permission permission);
-
- /**
- * Checks if the specified permission is part of the
- * permission set in this entry.
- *
- * @param permission the permission to be checked for.
- *
- * @return true if the permission is part of the
- * permission set in this entry, false otherwise.
- */
- public boolean checkPermission(Permission permission);
-
- /**
- * Returns an enumeration of the permissions in this ACL entry.
- *
- * @return an enumeration of the permissions in this ACL entry.
- */
- public Enumeration<Permission> permissions();
-
- /**
- * Returns a string representation of the contents of this ACL entry.
- *
- * @return a string representation of the contents.
- */
- public String toString();
-
- /**
- * Clones this ACL entry.
- *
- * @return a clone of this ACL entry.
- */
- public Object clone();
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/AclNotFoundException.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.security.acl;
-
-/**
- * This is an exception that is thrown whenever a reference is made to a
- * non-existent ACL (Access Control List).
- *
- * @author Satish Dharmaraj
- */
-public class AclNotFoundException extends Exception {
-
- private static final long serialVersionUID = 5684295034092681791L;
-
- /**
- * Constructs an AclNotFoundException.
- */
- public AclNotFoundException() {
- }
-
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/Group.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.security.acl;
-
-import java.util.Enumeration;
-import java.security.Principal;
-
-/**
- * This interface is used to represent a group of principals. (A principal
- * represents an entity such as an individual user or a company). <p>
- *
- * Note that Group extends Principal. Thus, either a Principal or a Group can
- * be passed as an argument to methods containing a Principal parameter. For
- * example, you can add either a Principal or a Group to a Group object by
- * calling the object's {@code addMember} method, passing it the
- * Principal or Group.
- *
- * @author Satish Dharmaraj
- */
-public interface Group extends Principal {
-
- /**
- * Adds the specified member to the group.
- *
- * @param user the principal to add to this group.
- *
- * @return true if the member was successfully added,
- * false if the principal was already a member.
- */
- public boolean addMember(Principal user);
-
- /**
- * Removes the specified member from the group.
- *
- * @param user the principal to remove from this group.
- *
- * @return true if the principal was removed, or
- * false if the principal was not a member.
- */
- public boolean removeMember(Principal user);
-
- /**
- * Returns true if the passed principal is a member of the group.
- * This method does a recursive search, so if a principal belongs to a
- * group which is a member of this group, true is returned.
- *
- * @param member the principal whose membership is to be checked.
- *
- * @return true if the principal is a member of this group,
- * false otherwise.
- */
- public boolean isMember(Principal member);
-
-
- /**
- * Returns an enumeration of the members in the group.
- * The returned objects can be instances of either Principal
- * or Group (which is a subclass of Principal).
- *
- * @return an enumeration of the group members.
- */
- public Enumeration<? extends Principal> members();
-
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/LastOwnerException.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.security.acl;
-
-/**
- * This is an exception that is thrown whenever an attempt is made to delete
- * the last owner of an Access Control List.
- *
- * @see java.security.acl.Owner#deleteOwner
- *
- * @author Satish Dharmaraj
- */
-public class LastOwnerException extends Exception {
-
- private static final long serialVersionUID = -5141997548211140359L;
-
- /**
- * Constructs a LastOwnerException.
- */
- public LastOwnerException() {
- }
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/NotOwnerException.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.security.acl;
-
-/**
- * This is an exception that is thrown whenever the modification of an object
- * (such as an Access Control List) is only allowed to be done by an owner of
- * the object, but the Principal attempting the modification is not an owner.
- *
- * @author Satish Dharmaraj
- */
-public class NotOwnerException extends Exception {
-
- private static final long serialVersionUID = -5555597911163362399L;
-
- /**
- * Constructs a NotOwnerException.
- */
- public NotOwnerException() {
- }
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/Owner.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.security.acl;
-
-import java.security.Principal;
-
-/**
- * Interface for managing owners of Access Control Lists (ACLs) or ACL
- * configurations. (Note that the Acl interface in the
- * {@code java.security.acl} package extends this Owner
- * interface.) The initial owner Principal should be specified as an
- * argument to the constructor of the class implementing this interface.
- *
- * @see java.security.acl.Acl
- *
- */
-public interface Owner {
-
- /**
- * Adds an owner. Only owners can modify ACL contents. The caller
- * principal must be an owner of the ACL in order to invoke this method.
- * That is, only an owner can add another owner. The initial owner is
- * configured at ACL construction time.
- *
- * @param caller the principal invoking this method. It must be an owner
- * of the ACL.
- *
- * @param owner the owner that should be added to the list of owners.
- *
- * @return true if successful, false if owner is already an owner.
- * @exception NotOwnerException if the caller principal is not an owner
- * of the ACL.
- */
- public boolean addOwner(Principal caller, Principal owner)
- throws NotOwnerException;
-
- /**
- * Deletes an owner. If this is the last owner in the ACL, an exception is
- * raised.<p>
- *
- * The caller principal must be an owner of the ACL in order to invoke
- * this method.
- *
- * @param caller the principal invoking this method. It must be an owner
- * of the ACL.
- *
- * @param owner the owner to be removed from the list of owners.
- *
- * @return true if the owner is removed, false if the owner is not part
- * of the list of owners.
- *
- * @exception NotOwnerException if the caller principal is not an owner
- * of the ACL.
- *
- * @exception LastOwnerException if there is only one owner left, so that
- * deleteOwner would leave the ACL owner-less.
- */
- public boolean deleteOwner(Principal caller, Principal owner)
- throws NotOwnerException, LastOwnerException;
-
- /**
- * Returns true if the given principal is an owner of the ACL.
- *
- * @param owner the principal to be checked to determine whether or not
- * it is an owner.
- *
- * @return true if the passed principal is in the list of owners, false
- * if not.
- */
- public boolean isOwner(Principal owner);
-
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/Permission.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package java.security.acl;
-
-
-/**
- * This interface represents a permission, such as that used to grant
- * a particular type of access to a resource.
- *
- * @author Satish Dharmaraj
- */
-public interface Permission {
-
- /**
- * Returns true if the object passed matches the permission represented
- * in this interface.
- *
- * @param another the Permission object to compare with.
- *
- * @return true if the Permission objects are equal, false otherwise
- */
- public boolean equals(Object another);
-
- /**
- * Prints a string representation of this permission.
- *
- * @return the string representation of the permission.
- */
- public String toString();
-
-}
--- a/jdk/src/java.security.acl/share/classes/java/security/acl/package-info.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * The classes and interfaces in this package have been
- * superseded by classes in the java.security package.
- * See that package and, for example, java.security.Permission for details.
- *
- * @since 1.1
- */
-package java.security.acl;
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/AclEntryImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.security.acl;
-
-import java.util.*;
-import java.security.Principal;
-import java.security.acl.*;
-
-/**
- * This is a class that describes one entry that associates users
- * or groups with permissions in the ACL.
- * The entry may be used as a way of granting or denying permissions.
- * @author Satish Dharmaraj
- */
-public class AclEntryImpl implements AclEntry {
- private Principal user = null;
- private Vector<Permission> permissionSet = new Vector<>(10, 10);
- private boolean negative = false;
-
- /**
- * Construct an ACL entry that associates a user with permissions
- * in the ACL.
- * @param user The user that is associated with this entry.
- */
- public AclEntryImpl(Principal user) {
- this.user = user;
- }
-
- /**
- * Construct a null ACL entry
- */
- public AclEntryImpl() {
- }
-
- /**
- * Sets the principal in the entity. If a group or a
- * principal had already been set, a false value is
- * returned, otherwise a true value is returned.
- * @param user The user that is associated with this entry.
- * @return true if the principal is set, false if there is
- * one already.
- */
- public boolean setPrincipal(Principal user) {
- if (this.user != null)
- return false;
- this.user = user;
- return true;
- }
-
- /**
- * This method sets the ACL to have negative permissions.
- * That is the user or group is denied the permission set
- * specified in the entry.
- */
- public void setNegativePermissions() {
- negative = true;
- }
-
- /**
- * Returns true if this is a negative ACL.
- */
- public boolean isNegative() {
- return negative;
- }
-
- /**
- * A principal or a group can be associated with multiple
- * permissions. This method adds a permission to the ACL entry.
- * @param permission The permission to be associated with
- * the principal or the group in the entry.
- * @return true if the permission was added, false if the
- * permission was already part of the permission set.
- */
- public boolean addPermission(Permission permission) {
-
- if (permissionSet.contains(permission))
- return false;
-
- permissionSet.addElement(permission);
-
- return true;
- }
-
- /**
- * The method disassociates the permission from the Principal
- * or the Group in this ACL entry.
- * @param permission The permission to be disassociated with
- * the principal or the group in the entry.
- * @return true if the permission is removed, false if the
- * permission is not part of the permission set.
- */
- public boolean removePermission(Permission permission) {
- return permissionSet.removeElement(permission);
- }
-
- /**
- * Checks if the passed permission is part of the allowed
- * permission set in this entry.
- * @param permission The permission that has to be part of
- * the permission set in the entry.
- * @return true if the permission passed is part of the
- * permission set in the entry, false otherwise.
- */
- public boolean checkPermission(Permission permission) {
- return permissionSet.contains(permission);
- }
-
- /**
- * return an enumeration of the permissions in this ACL entry.
- */
- public Enumeration<Permission> permissions() {
- return permissionSet.elements();
- }
-
- /**
- * Return a string representation of the contents of the ACL entry.
- */
- public String toString() {
- StringBuffer s = new StringBuffer();
- if (negative)
- s.append("-");
- else
- s.append("+");
- if (user instanceof Group)
- s.append("Group.");
- else
- s.append("User.");
- s.append(user + "=");
- Enumeration<Permission> e = permissions();
- while(e.hasMoreElements()) {
- Permission p = e.nextElement();
- s.append(p);
- if (e.hasMoreElements())
- s.append(",");
- }
- return new String(s);
- }
-
- /**
- * Clones an AclEntry.
- */
- @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
- public synchronized Object clone() {
- AclEntryImpl cloned;
- cloned = new AclEntryImpl(user);
- cloned.permissionSet = (Vector<Permission>) permissionSet.clone();
- cloned.negative = negative;
- return cloned;
- }
-
- /**
- * Return the Principal associated in this ACL entry.
- * The method returns null if the entry uses a group
- * instead of a principal.
- */
- public Principal getPrincipal() {
- return user;
- }
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/AclImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,408 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.io.*;
-import java.util.*;
-import java.security.Principal;
-import java.security.acl.*;
-
-/**
- * An Access Control List (ACL) is encapsulated by this class.
- * @author Satish Dharmaraj
- */
-public class AclImpl extends OwnerImpl implements Acl {
- //
- // Maintain four tables. one each for positive and negative
- // ACLs. One each depending on whether the entity is a group
- // or principal.
- //
- private Hashtable<Principal, AclEntry> allowedUsersTable =
- new Hashtable<>(23);
- private Hashtable<Principal, AclEntry> allowedGroupsTable =
- new Hashtable<>(23);
- private Hashtable<Principal, AclEntry> deniedUsersTable =
- new Hashtable<>(23);
- private Hashtable<Principal, AclEntry> deniedGroupsTable =
- new Hashtable<>(23);
- private String aclName = null;
- private Vector<Permission> zeroSet = new Vector<>(1,1);
-
-
- /**
- * Constructor for creating an empty ACL.
- */
- public AclImpl(Principal owner, String name) {
- super(owner);
- try {
- setName(owner, name);
- } catch (Exception e) {}
- }
-
- /**
- * Sets the name of the ACL.
- * @param caller the principal who is invoking this method.
- * @param name the name of the ACL.
- * @exception NotOwnerException if the caller principal is
- * not on the owners list of the Acl.
- */
- public void setName(Principal caller, String name)
- throws NotOwnerException
- {
- if (!isOwner(caller))
- throw new NotOwnerException();
-
- aclName = name;
- }
-
- /**
- * Returns the name of the ACL.
- * @return the name of the ACL.
- */
- public String getName() {
- return aclName;
- }
-
- /**
- * Adds an ACL entry to this ACL. An entry associates a
- * group or a principal with a set of permissions. Each
- * user or group can have one positive ACL entry and one
- * negative ACL entry. If there is one of the type (negative
- * or positive) already in the table, a false value is returned.
- * The caller principal must be a part of the owners list of
- * the ACL in order to invoke this method.
- * @param caller the principal who is invoking this method.
- * @param entry the ACL entry that must be added to the ACL.
- * @return true on success, false if the entry is already present.
- * @exception NotOwnerException if the caller principal
- * is not on the owners list of the Acl.
- */
- public synchronized boolean addEntry(Principal caller, AclEntry entry)
- throws NotOwnerException
- {
- if (!isOwner(caller))
- throw new NotOwnerException();
-
- Hashtable<Principal, AclEntry> aclTable = findTable(entry);
- Principal key = entry.getPrincipal();
-
- if (aclTable.get(key) != null)
- return false;
-
- aclTable.put(key, entry);
- return true;
- }
-
- /**
- * Removes an ACL entry from this ACL.
- * The caller principal must be a part of the owners list of the ACL
- * in order to invoke this method.
- * @param caller the principal who is invoking this method.
- * @param entry the ACL entry that must be removed from the ACL.
- * @return true on success, false if the entry is not part of the ACL.
- * @exception NotOwnerException if the caller principal is not
- * the owners list of the Acl.
- */
- public synchronized boolean removeEntry(Principal caller, AclEntry entry)
- throws NotOwnerException
- {
- if (!isOwner(caller))
- throw new NotOwnerException();
-
- Hashtable<Principal, AclEntry> aclTable = findTable(entry);
- Principal key = entry.getPrincipal();
-
- AclEntry o = aclTable.remove(key);
- return (o != null);
- }
-
- /**
- * This method returns the set of allowed permissions for the
- * specified principal. This set of allowed permissions is calculated
- * as follows:
- *
- * If there is no entry for a group or a principal an empty permission
- * set is assumed.
- *
- * The group positive permission set is the union of all
- * the positive permissions of each group that the individual belongs to.
- * The group negative permission set is the union of all
- * the negative permissions of each group that the individual belongs to.
- * If there is a specific permission that occurs in both
- * the postive permission set and the negative permission set,
- * it is removed from both. The group positive and negatoive permission
- * sets are calculated.
- *
- * The individial positive permission set and the individual negative
- * permission set is then calculated. Again abscence of an entry means
- * the empty set.
- *
- * The set of permissions granted to the principal is then calculated using
- * the simple rule: Individual permissions always override the Group permissions.
- * Specifically, individual negative permission set (specific
- * denial of permissions) overrides the group positive permission set.
- * And the individual positive permission set override the group negative
- * permission set.
- *
- * @param user the principal for which the ACL entry is returned.
- * @return The resulting permission set that the principal is allowed.
- */
- public synchronized Enumeration<Permission> getPermissions(Principal user) {
-
- Enumeration<Permission> individualPositive;
- Enumeration<Permission> individualNegative;
- Enumeration<Permission> groupPositive;
- Enumeration<Permission> groupNegative;
-
- //
- // canonicalize the sets. That is remove common permissions from
- // positive and negative sets.
- //
- groupPositive =
- subtract(getGroupPositive(user), getGroupNegative(user));
- groupNegative =
- subtract(getGroupNegative(user), getGroupPositive(user));
- individualPositive =
- subtract(getIndividualPositive(user), getIndividualNegative(user));
- individualNegative =
- subtract(getIndividualNegative(user), getIndividualPositive(user));
-
- //
- // net positive permissions is individual positive permissions
- // plus (group positive - individual negative).
- //
- Enumeration<Permission> temp1 =
- subtract(groupPositive, individualNegative);
- Enumeration<Permission> netPositive =
- union(individualPositive, temp1);
-
- // recalculate the enumeration since we lost it in performing the
- // subtraction
- //
- individualPositive =
- subtract(getIndividualPositive(user), getIndividualNegative(user));
- individualNegative =
- subtract(getIndividualNegative(user), getIndividualPositive(user));
-
- //
- // net negative permissions is individual negative permissions
- // plus (group negative - individual positive).
- //
- temp1 = subtract(groupNegative, individualPositive);
- Enumeration<Permission> netNegative = union(individualNegative, temp1);
-
- return subtract(netPositive, netNegative);
- }
-
- /**
- * This method checks whether or not the specified principal
- * has the required permission. If permission is denied
- * permission false is returned, a true value is returned otherwise.
- * This method does not authenticate the principal. It presumes that
- * the principal is a valid authenticated principal.
- * @param principal the name of the authenticated principal
- * @param permission the permission that the principal must have.
- * @return true of the principal has the permission desired, false
- * otherwise.
- */
- public boolean checkPermission(Principal principal, Permission permission)
- {
- Enumeration<Permission> permSet = getPermissions(principal);
- while (permSet.hasMoreElements()) {
- Permission p = permSet.nextElement();
- if (p.equals(permission))
- return true;
- }
- return false;
- }
-
- /**
- * returns an enumeration of the entries in this ACL.
- */
- public synchronized Enumeration<AclEntry> entries() {
- return new AclEnumerator(this,
- allowedUsersTable, allowedGroupsTable,
- deniedUsersTable, deniedGroupsTable);
- }
-
- /**
- * return a stringified version of the
- * ACL.
- */
- public String toString() {
- StringBuilder sb = new StringBuilder();
- Enumeration<AclEntry> entries = entries();
- while (entries.hasMoreElements()) {
- AclEntry entry = entries.nextElement();
- sb.append(entry.toString().trim());
- sb.append("\n");
- }
-
- return sb.toString();
- }
-
- //
- // Find the table that this entry belongs to. There are 4
- // tables that are maintained. One each for postive and
- // negative ACLs and one each for groups and users.
- // This method figures out which
- // table is the one that this AclEntry belongs to.
- //
- private Hashtable<Principal, AclEntry> findTable(AclEntry entry) {
- Hashtable<Principal, AclEntry> aclTable = null;
-
- Principal p = entry.getPrincipal();
- if (p instanceof Group) {
- if (entry.isNegative())
- aclTable = deniedGroupsTable;
- else
- aclTable = allowedGroupsTable;
- } else {
- if (entry.isNegative())
- aclTable = deniedUsersTable;
- else
- aclTable = allowedUsersTable;
- }
- return aclTable;
- }
-
- //
- // returns the set e1 U e2.
- //
- private static Enumeration<Permission> union(Enumeration<Permission> e1,
- Enumeration<Permission> e2) {
- Vector<Permission> v = new Vector<>(20, 20);
-
- while (e1.hasMoreElements())
- v.addElement(e1.nextElement());
-
- while (e2.hasMoreElements()) {
- Permission o = e2.nextElement();
- if (!v.contains(o))
- v.addElement(o);
- }
-
- return v.elements();
- }
-
- //
- // returns the set e1 - e2.
- //
- private Enumeration<Permission> subtract(Enumeration<Permission> e1,
- Enumeration<Permission> e2) {
- Vector<Permission> v = new Vector<>(20, 20);
-
- while (e1.hasMoreElements())
- v.addElement(e1.nextElement());
-
- while (e2.hasMoreElements()) {
- Permission o = e2.nextElement();
- if (v.contains(o))
- v.removeElement(o);
- }
-
- return v.elements();
- }
-
- private Enumeration<Permission> getGroupPositive(Principal user) {
- Enumeration<Permission> groupPositive = zeroSet.elements();
- Enumeration<Principal> e = allowedGroupsTable.keys();
- while (e.hasMoreElements()) {
- Group g = (Group)e.nextElement();
- if (g.isMember(user)) {
- AclEntry ae = allowedGroupsTable.get(g);
- groupPositive = union(ae.permissions(), groupPositive);
- }
- }
- return groupPositive;
- }
-
- private Enumeration<Permission> getGroupNegative(Principal user) {
- Enumeration<Permission> groupNegative = zeroSet.elements();
- Enumeration<Principal> e = deniedGroupsTable.keys();
- while (e.hasMoreElements()) {
- Group g = (Group)e.nextElement();
- if (g.isMember(user)) {
- AclEntry ae = deniedGroupsTable.get(g);
- groupNegative = union(ae.permissions(), groupNegative);
- }
- }
- return groupNegative;
- }
-
- private Enumeration<Permission> getIndividualPositive(Principal user) {
- Enumeration<Permission> individualPositive = zeroSet.elements();
- AclEntry ae = allowedUsersTable.get(user);
- if (ae != null)
- individualPositive = ae.permissions();
- return individualPositive;
- }
-
- private Enumeration<Permission> getIndividualNegative(Principal user) {
- Enumeration<Permission> individualNegative = zeroSet.elements();
- AclEntry ae = deniedUsersTable.get(user);
- if (ae != null)
- individualNegative = ae.permissions();
- return individualNegative;
- }
-}
-
-final class AclEnumerator implements Enumeration<AclEntry> {
- Acl acl;
- Enumeration<AclEntry> u1, u2, g1, g2;
-
- AclEnumerator(Acl acl, Hashtable<?,AclEntry> u1, Hashtable<?,AclEntry> g1,
- Hashtable<?,AclEntry> u2, Hashtable<?,AclEntry> g2) {
- this.acl = acl;
- this.u1 = u1.elements();
- this.u2 = u2.elements();
- this.g1 = g1.elements();
- this.g2 = g2.elements();
- }
-
- public boolean hasMoreElements() {
- return (u1.hasMoreElements() ||
- u2.hasMoreElements() ||
- g1.hasMoreElements() ||
- g2.hasMoreElements());
- }
-
- public AclEntry nextElement()
- {
- AclEntry o;
- synchronized (acl) {
- if (u1.hasMoreElements())
- return u1.nextElement();
- if (u2.hasMoreElements())
- return u2.nextElement();
- if (g1.hasMoreElements())
- return g1.nextElement();
- if (g2.hasMoreElements())
- return g2.nextElement();
- }
- throw new NoSuchElementException("Acl Enumerator");
- }
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/AllPermissionsImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1996, 1997, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.security.Principal;
-import java.security.acl.*;
-
-/**
- * This class implements the principal interface for the set of all permissions.
- * @author Satish Dharmaraj
- */
-public class AllPermissionsImpl extends PermissionImpl {
-
- public AllPermissionsImpl(String s) {
- super(s);
- }
-
- /**
- * This function returns true if the permission passed matches the permission represented in
- * this interface.
- * @param another The Permission object to compare with.
- * @returns true always
- */
- public boolean equals(Permission another) {
- return true;
- }
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/GroupImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.util.*;
-import java.security.*;
-import java.security.acl.*;
-
-/**
- * This class implements a group of principals.
- * @author Satish Dharmaraj
- */
-public class GroupImpl implements Group {
- private Vector<Principal> groupMembers = new Vector<>(50, 100);
- private String group;
-
- /**
- * Constructs a Group object with no members.
- * @param groupName the name of the group
- */
- public GroupImpl(String groupName) {
- this.group = groupName;
- }
-
- /**
- * adds the specified member to the group.
- * @param user The principal to add to the group.
- * @return true if the member was added - false if the
- * member could not be added.
- */
- public boolean addMember(Principal user) {
- if (groupMembers.contains(user))
- return false;
-
- // do not allow groups to be added to itself.
- if (group.equals(user.toString()))
- throw new IllegalArgumentException();
-
- groupMembers.addElement(user);
- return true;
- }
-
- /**
- * removes the specified member from the group.
- * @param user The principal to remove from the group.
- * @param true if the principal was removed false if
- * the principal was not a member
- */
- public boolean removeMember(Principal user) {
- return groupMembers.removeElement(user);
- }
-
- /**
- * returns the enumeration of the members in the group.
- */
- public Enumeration<? extends Principal> members() {
- return groupMembers.elements();
- }
-
- /**
- * This function returns true if the group passed matches
- * the group represented in this interface.
- * @param another The group to compare this group to.
- */
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj instanceof Group == false) {
- return false;
- }
- Group another = (Group)obj;
- return group.equals(another.toString());
- }
-
- // equals(Group) for compatibility
- public boolean equals(Group another) {
- return equals((Object)another);
- }
-
- /**
- * Prints a stringified version of the group.
- */
- public String toString() {
- return group;
- }
-
- /**
- * return a hashcode for the principal.
- */
- public int hashCode() {
- return group.hashCode();
- }
-
- /**
- * returns true if the passed principal is a member of the group.
- * @param member The principal whose membership must be checked for.
- * @return true if the principal is a member of this group,
- * false otherwise
- */
- public boolean isMember(Principal member) {
-
- //
- // if the member is part of the group (common case), return true.
- // if not, recursively search depth first in the group looking for the
- // principal.
- //
- if (groupMembers.contains(member)) {
- return true;
- } else {
- Vector<Group> alreadySeen = new Vector<>(10);
- return isMemberRecurse(member, alreadySeen);
- }
- }
-
- /**
- * return the name of the principal.
- */
- public String getName() {
- return group;
- }
-
- //
- // This function is the recursive search of groups for this
- // implementation of the Group. The search proceeds building up
- // a vector of already seen groups. Only new groups are considered,
- // thereby avoiding loops.
- //
- boolean isMemberRecurse(Principal member, Vector<Group> alreadySeen) {
- Enumeration<? extends Principal> e = members();
- while (e.hasMoreElements()) {
- boolean mem = false;
- Principal p = (Principal) e.nextElement();
-
- // if the member is in this collection, return true
- if (p.equals(member)) {
- return true;
- } else if (p instanceof GroupImpl) {
- //
- // if not recurse if the group has not been checked already.
- // Can call method in this package only if the object is an
- // instance of this class. Otherwise call the method defined
- // in the interface. (This can lead to a loop if a mixture of
- // implementations form a loop, but we live with this improbable
- // case rather than clutter the interface by forcing the
- // implementation of this method.)
- //
- GroupImpl g = (GroupImpl) p;
- alreadySeen.addElement(this);
- if (!alreadySeen.contains(g))
- mem = g.isMemberRecurse(member, alreadySeen);
- } else if (p instanceof Group) {
- Group g = (Group) p;
- if (!alreadySeen.contains(g))
- mem = g.isMember(member);
- }
-
- if (mem)
- return mem;
- }
- return false;
- }
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/OwnerImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.util.*;
-import java.security.*;
-import java.security.acl.*;
-
-/**
- * Class implementing the Owner interface. The
- * initial owner principal is configured as
- * part of the constructor.
- * @author Satish Dharmaraj
- */
-public class OwnerImpl implements Owner {
- private Group ownerGroup;
-
- public OwnerImpl(Principal owner) {
- ownerGroup = new GroupImpl("AclOwners");
- ownerGroup.addMember(owner);
- }
-
- /**
- * Adds an owner. Owners can modify ACL contents and can disassociate
- * ACLs from the objects they protect in the AclConfig interface.
- * The caller principal must be a part of the owners list of the ACL in
- * order to invoke this method. The initial owner is configured
- * at ACL construction time.
- * @param caller the principal who is invoking this method.
- * @param owner The owner that should be added to the owners list.
- * @return true if success, false if already an owner.
- * @exception NotOwnerException if the caller principal is not on
- * the owners list of the Acl.
- */
- public synchronized boolean addOwner(Principal caller, Principal owner)
- throws NotOwnerException
- {
- if (!isOwner(caller))
- throw new NotOwnerException();
-
- ownerGroup.addMember(owner);
- return false;
- }
-
- /**
- * Delete owner. If this is the last owner in the ACL, an exception is
- * raised.
- * The caller principal must be a part of the owners list of the ACL in
- * order to invoke this method.
- * @param caller the principal who is invoking this method.
- * @param owner The owner to be removed from the owners list.
- * @return true if the owner is removed, false if the owner is not part
- * of the owners list.
- * @exception NotOwnerException if the caller principal is not on
- * the owners list of the Acl.
- * @exception LastOwnerException if there is only one owner left in the group, then
- * deleteOwner would leave the ACL owner-less. This exception is raised in such a case.
- */
- public synchronized boolean deleteOwner(Principal caller, Principal owner)
- throws NotOwnerException, LastOwnerException
- {
- if (!isOwner(caller))
- throw new NotOwnerException();
-
- Enumeration<? extends Principal> e = ownerGroup.members();
- //
- // check if there is atleast 2 members left.
- //
- Object o = e.nextElement();
- if (e.hasMoreElements())
- return ownerGroup.removeMember(owner);
- else
- throw new LastOwnerException();
-
- }
-
- /**
- * returns if the given principal belongs to the owner list.
- * @param owner The owner to check if part of the owners list
- * @return true if the passed principal is in the owner list, false if not.
- */
- public synchronized boolean isOwner(Principal owner) {
- return ownerGroup.isMember(owner);
- }
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/PermissionImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 1996, 1999, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.security.Principal;
-import java.security.acl.*;
-
-/**
- * The PermissionImpl class implements the permission
- * interface for permissions that are strings.
- * @author Satish Dharmaraj
- */
-public class PermissionImpl implements Permission {
-
- private String permission;
-
- /**
- * Construct a permission object using a string.
- * @param permission the stringified version of the permission.
- */
- public PermissionImpl(String permission) {
- this.permission = permission;
- }
-
- /**
- * This function returns true if the object passed matches the permission
- * represented in this interface.
- * @param another The Permission object to compare with.
- * @return true if the Permission objects are equal, false otherwise
- */
- public boolean equals(Object another) {
- if (another instanceof Permission) {
- Permission p = (Permission) another;
- return permission.equals(p.toString());
- } else {
- return false;
- }
- }
-
- /**
- * Prints a stringified version of the permission.
- * @return the string representation of the Permission.
- */
- public String toString() {
- return permission;
- }
-
- /**
- * Returns a hashcode for this PermissionImpl.
- *
- * @return a hashcode for this PermissionImpl.
- */
- public int hashCode() {
- return toString().hashCode();
- }
-
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/PrincipalImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.security.*;
-
-/**
- * This class implements the principal interface.
- *
- * @author Satish Dharmaraj
- */
-public class PrincipalImpl implements Principal {
-
- private String user;
-
- /**
- * Construct a principal from a string user name.
- * @param user The string form of the principal name.
- */
- public PrincipalImpl(String user) {
- this.user = user;
- }
-
- /**
- * This function returns true if the object passed matches
- * the principal represented in this implementation
- * @param another the Principal to compare with.
- * @return true if the Principal passed is the same as that
- * encapsulated in this object, false otherwise
- */
- public boolean equals(Object another) {
- if (another instanceof PrincipalImpl) {
- PrincipalImpl p = (PrincipalImpl) another;
- return user.equals(p.toString());
- } else
- return false;
- }
-
- /**
- * Prints a stringified version of the principal.
- */
- public String toString() {
- return user;
- }
-
- /**
- * return a hashcode for the principal.
- */
- public int hashCode() {
- return user.hashCode();
- }
-
- /**
- * return the name of the principal.
- */
- public String getName() {
- return user;
- }
-
-}
--- a/jdk/src/java.security.acl/share/classes/sun/security/acl/WorldGroupImpl.java Fri Feb 06 19:49:20 2015 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.acl;
-
-import java.security.*;
-
-/**
- * This class implements a group of principals.
- * @author Satish Dharmaraj
- */
-public class WorldGroupImpl extends GroupImpl {
-
- public WorldGroupImpl(String s) {
- super(s);
- }
-
- /**
- * returns true for all passed principals
- * @param member The principal whose membership must be checked in this Group.
- * @return true always since this is the "world" group.
- */
- public boolean isMember(Principal member) {
- return true;
- }
-}
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java Mon Feb 09 09:52:48 2015 -0800
@@ -60,16 +60,6 @@
private static boolean DEBUG = Krb5.DEBUG;
private static final char[] hexConst = "0123456789ABCDEF".toCharArray();
- private static final MessageDigest md;
-
- static {
- try {
- md = MessageDigest.getInstance("MD5");
- } catch (NoSuchAlgorithmException ex) {
- throw new RuntimeException("Impossible");
- }
- }
-
/**
* Constructs an AP-REQ message to send to the peer.
* @param tgsCred the <code>Credentials</code> to be used to construct the
@@ -99,10 +89,10 @@
* @param tgsCred the <code>Credentials</code> to be used to construct the
* AP Request protocol message.
* @param mutualRequired Whether mutual authentication is required
- * @param useSubkey Whether the subkey is to be used to protect this
+ * @param useSubKey Whether the subkey is to be used to protect this
* specific application session. If this is not set then the
* session key from the ticket will be used.
- * @param checksum checksum of the application data that accompanies
+ * @param cksum checksum of the application data that accompanies
* the KRB_AP_REQ.
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
@@ -142,8 +132,8 @@
* Constructs an AP-REQ message from the bytes received from the
* peer.
* @param message The message received from the peer
- * @param keys <code>EncrtyptionKey</code>s to decrypt the message;
- * key selected will depend on etype used to encrypte data
+ * @param cred <code>KrbAcceptCredential</code> containing keys to decrypt
+ * the message; key selected will depend on etype used to encrypt data
* @throws KrbException for any Kerberos protocol specific error
* @throws IOException for any IO related errors
* (e.g. socket operations)
@@ -311,7 +301,14 @@
if (!authenticator.ctime.inClockSkew())
throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
- byte[] hash = md.digest(apReqMessg.authenticator.cipher);
+ byte[] hash;
+ try {
+ hash = MessageDigest.getInstance("MD5")
+ .digest(apReqMessg.authenticator.cipher);
+ } catch (NoSuchAlgorithmException ex) {
+ throw new AssertionError("Impossible");
+ }
+
char[] h = new char[hash.length * 2];
for (int i=0; i<hash.length; i++) {
h[2*i] = hexConst[(hash[i]&0xff)>>4];
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/de/TimeZoneNames_de.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Venezuelanische Zeit", "VET",
"Venezuelanische Sommerzeit", "VEST",
"Venezuelanische Zeit", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/es/TimeZoneNames_es.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Hora de Venezuela", "VET",
"Hora de verano de Venezuela", "VEST",
"Hora de Venezuela", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/fr/TimeZoneNames_fr.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Heure du Venezuela", "VET",
"Heure d'\u00e9t\u00e9 du Venezuela", "VEST",
"Heure du Venezuela", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/it/TimeZoneNames_it.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Ora del Venezuela", "VET",
"Ora estiva del Venezuela", "VEST",
"Ora del Venezuela", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ja/TimeZoneNames_ja.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"\u30d9\u30cd\u30ba\u30a8\u30e9\u6642\u9593", "VET",
"\u30d9\u30cd\u30ba\u30a8\u30e9\u590f\u6642\u9593", "VEST",
"\u30D9\u30CD\u30BA\u30A8\u30E9\u6642\u9593", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/ko/TimeZoneNames_ko.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"\ubca0\ub124\uc218\uc5d8\ub77c \uc2dc\uac04", "VET",
"\ubca0\ub124\uc218\uc5d8\ub77c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "VEST",
"\uBCA0\uB124\uC218\uC5D8\uB77C \uD45C\uC900\uC2DC", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/pt/TimeZoneNames_pt_BR.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Fuso hor\u00e1rio da Venezuela", "VET",
"Fuso hor\u00e1rio de ver\u00e3o da Venezuela", "VEST",
"Hor\u00E1rio da Venezuela", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/sv/TimeZoneNames_sv.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"Venezuela, normaltid", "VET",
"Venezuela, sommartid", "VEST",
"Venezuelansk tid", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_CN.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"\u59d4\u5185\u745e\u62c9\u65f6\u95f4", "VET",
"\u59d4\u5185\u745e\u62c9\u590f\u4ee4\u65f6", "VEST",
"\u59D4\u5185\u745E\u62C9\u65F6\u95F4", "VET"}},
--- a/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.localedata/share/classes/sun/util/resources/zh/TimeZoneNames_zh_TW.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -409,7 +409,7 @@
{"America/Buenos_Aires", AGT},
{"America/Cambridge_Bay", MST},
{"America/Campo_Grande", AMT},
- {"America/Cancun", CST},
+ {"America/Cancun", EST},
{"America/Caracas", new String[] {"\u59d4\u5167\u745e\u62c9\u6642\u9593", "VET",
"\u59d4\u5167\u745e\u62c9\u590f\u4ee4\u6642\u9593", "VEST",
"\u59D4\u5167\u745E\u62C9\u6642\u9593", "VET"}},
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c Mon Feb 09 09:52:48 2015 -0800
@@ -316,11 +316,12 @@
if (isaCls == 0) {
jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
CHECK_NULL(c);
+ isaCtrID = (*env)->GetMethodID(env, c, "<init>",
+ "(Ljava/net/InetAddress;I)V");
+ CHECK_NULL(isaCtrID);
isaCls = (*env)->NewGlobalRef(env, c);
CHECK_NULL(isaCls);
(*env)->DeleteLocalRef(env, c);
- isaCtrID = (*env)->GetMethodID(env, isaCls, "<init>",
- "(Ljava/net/InetAddress;I)V");
}
}
--- a/jdk/test/Makefile Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/Makefile Mon Feb 09 09:52:48 2015 -0800
@@ -267,8 +267,8 @@
EXTRA_JTREG_OPTIONS += -concurrency:$(CONCURRENCY)
endif
-# Default JTREG to run (win32 script works for everybody)
-JTREG = $(JT_HOME)/win32/bin/jtreg
+# Default JTREG to run
+JTREG = $(JT_HOME)/bin/jtreg
# run in agentvm mode
JTREG_BASIC_OPTIONS += -agentvm
# Only run automatic tests
--- a/jdk/test/ProblemList.txt Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/ProblemList.txt Mon Feb 09 09:52:48 2015 -0800
@@ -1,6 +1,6 @@
###########################################################################
#
-# Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -123,7 +123,6 @@
# 8029891
java/lang/ClassLoader/deadlock/GetResource.java generic-all
-
############################################################################
# jdk_instrument
@@ -132,6 +131,9 @@
java/lang/instrument/RedefineBigClass.sh generic-all
java/lang/instrument/RetransformBigClass.sh generic-all
+# 8072130
+java/lang/instrument/BootClassPath/BootClassPathTest.sh macosx-all
+
############################################################################
# jdk_management
@@ -139,6 +141,9 @@
# 8058492
java/lang/management/ThreadMXBean/FindDeadlocks.java generic-all
+# 8069286
+java/lang/management/MemoryMXBean/LowMemoryTest.java generic-all
+
############################################################################
# jdk_jmx
@@ -162,6 +167,9 @@
# 6988950
demo/jvmti/compiledMethodLoad/CompiledMethodLoadTest.java generic-all
+# 8071968
+javax/xml/ws/8046817/GenerateEnumSchema.java windows-all
+
############################################################################
# jdk_net
@@ -290,15 +298,18 @@
# 8043571
com/sun/jdi/RepStep.java generic-all
-# 8044419
-com/sun/jdi/JdbReadTwiceTest.sh generic-all
-
# 8058616
com/sun/jdi/RedefinePop.sh generic-all
# 8068645
com/sun/jdi/CatchPatternTest.sh generic-all
+# 8069402
+com/sun/jdi/ConnectedVMs.java generic-all
+
+# 8067354
+com/sun/jdi/GetLocalVariables4Test.sh windows-all
+
############################################################################
# jdk_util
@@ -317,6 +328,9 @@
# 8031482
sun/tools/jcmd/TestJcmdSanity.java windows-all
+# 8072131
+sun/tools/jmap/heapconfig/JMapHeapConfigTest.java macosx-all
+
# 8027668
sun/tools/jstatd/TestJstatdDefaults.java generic-all
sun/tools/jstatd/TestJstatdServer.java generic-all
--- a/jdk/test/com/sun/jdi/ImmutableResourceTest.sh Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/jdi/ImmutableResourceTest.sh Mon Feb 09 09:52:48 2015 -0800
@@ -92,7 +92,7 @@
#
echo "JDK under test is: $TESTJAVA"
#
-CP="-classpath ${TESTCLASSES}${PATHSEP}${TESTJAVA}/lib/tools.jar"
+CP="-classpath ${TESTCLASSES}"
# Compile the test class using the classpath we need:
#
env
--- a/jdk/test/com/sun/jdi/JITDebug.sh Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/jdi/JITDebug.sh Mon Feb 09 09:52:48 2015 -0800
@@ -103,15 +103,15 @@
#if running standalone (no test harness of any kind), compile the
#support files and the test case
${TESTJAVA}/bin/javac -d ${TESTCLASSES} \
- -classpath "$TESTJAVA/lib/tools.jar${PATHSEP}${TESTSRC}" \
+ -classpath "${TESTSRC}" \
TestScaffold.java VMConnection.java TargetListener.java TargetAdapter.java
${TESTJAVA}/bin/javac -d ${TESTCLASSES} \
- -classpath "$TESTJAVA/lib/tools.jar${PATHSEP}${TESTSRC}" -g \
+ -classpath "${TESTSRC}" -g \
JITDebug.java
fi
echo "JDK under test is: $TESTJAVA"
#
-CLASSPATH="$TESTJAVA/lib/tools.jar${PATHSEP}${TESTCLASSES}"
+CLASSPATH="${TESTCLASSES}"
export CLASSPATH
CP="-classpath \"${CLASSPATH}\""
#
--- a/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/jdi/JdbReadTwiceTest.sh Mon Feb 09 09:52:48 2015 -0800
@@ -204,27 +204,37 @@
clean
fi
+echo
+echo "+++++++++++++++++++++++++++++++++++"
+echo "Read an unreadable file - verify the read fails."
-if [ ! -r c:/ ] ; then
- # Can't make a file unreadable under MKS.
- echo
- echo "+++++++++++++++++++++++++++++++++++"
- echo "Read an unreadable file - verify the read fails."
- # If the file exists, we try to read it. The
- # read will fail.
- mkFiles $HOME/jdb.ini
- id > $HOME/jdb.ini
- chmod a-r $HOME/jdb.ini
- if grep -q "uid=" $HOME/jdb.ini ; then
- echo "Unable to make file unreadable, so test will fail. chmod: $HOME/jdb.ini"
- if grep -q "uid=0" $HOME/jdb.ini ; then
- echo "The test is running as root. Fix infrastructure!"
- fi
- fi
+canMakeUnreadable=No
+id > $HOME/jdb.ini
+if chmod a-r $HOME/jdb.ini
+then
+ grep -q 'uid=0(' $HOME/jdb.ini 2> /dev/null
+ case $? in
+ 0)
+ echo "Error! Can't make file unreadable running as root"
+ ;;
+ 1)
+ echo "Error! Can't make file unreadable for some other reason (windows?)"
+ ;;
+ *)
+ echo "OK. the file is unreadable"
+ canMakeUnreadable=Yes
+ ;;
+ esac
+else
+ echo "Error! Can't create or chmod file"
+fi
+
+if [ "$canMakeUnreadable" = "Yes" ]
+then
doit
failIfNot 1 "open: $HOME/jdb.ini"
- clean
fi
+clean
echo
@@ -246,8 +256,8 @@
doit
failIfNot 1 "from $fred"
- if [ ! -r c:/ ] ; then
- # Can't make a file unreadable under MKS
+ if [ "$canMakeUnreadable" = "Yes" ]
+ then
chmod a-r $fred
doit
failIfNot 1 "open: $fred"
--- a/jdk/test/com/sun/jdi/connect/spi/JdiLoadedByCustomLoader.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/jdi/connect/spi/JdiLoadedByCustomLoader.java Mon Feb 09 09:52:48 2015 -0800
@@ -22,9 +22,8 @@
*/
/*
- * Creates a URLClassLoader from 2 file URLs. The first
- * file URL is constructed from the given argument. The
- * second is the SDK tools.jar. Once created the test
+ * Creates a URLClassLoader from a file URL. The file URL
+ * is constructed from the given argument. Once created the test
* attempts to load another test case (ListConnectors)
* using the class loader and then it invokes the list()
* method.
@@ -39,13 +38,9 @@
public static void main(String args[]) throws Exception {
// create files from given arguments and tools.jar
File f1 = new File(args[0]);
- String home = System.getProperty("java.home");
- String tools = ".." + File.separatorChar + "lib" +
- File.separatorChar + "tools.jar";
- File f2 = (new File(home, tools)).getCanonicalFile();
// create class loader
- URL[] urls = { f1.toURL(), f2.toURL() };
+ URL[] urls = { f1.toURL() };
URLClassLoader cl = new URLClassLoader(urls);
// load ListConnectors using the class loader
--- a/jdk/test/com/sun/jdi/connect/spi/JdiLoadedByCustomLoader.sh Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/jdi/connect/spi/JdiLoadedByCustomLoader.sh Mon Feb 09 09:52:48 2015 -0800
@@ -68,7 +68,7 @@
$JAVAC -d "${TESTCLASSES}" "${TESTSRC}"/JdiLoadedByCustomLoader.java
mkdir "${SOMEOTHERDIR}"
-$JAVAC -d "${SOMEOTHERDIR}" -classpath "${TESTSRC}${PS}${TESTJAVA}/lib/tools.jar" \
+$JAVAC -d "${SOMEOTHERDIR}" -classpath "${TESTSRC}" \
"${TESTSRC}"/ListConnectors.java
# Run the test
--- a/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/management/HotSpotDiagnosticMXBean/CheckOrigin.java Mon Feb 09 09:52:48 2015 -0800
@@ -62,7 +62,7 @@
"-XX:+UseConcMarkSweepGC", // this will cause UseParNewGC to be FLAG_SET_ERGO
"-XX:+PrintGCDetails",
"-XX:Flags=" + flagsFile.getAbsolutePath(),
- "-cp", System.getProperty("test.class.path") + File.pathSeparator + getToolsJarPath(),
+ "-cp", System.getProperty("test.class.path"),
"CheckOrigin",
"-runtests");
@@ -137,8 +137,4 @@
vm.detach();
}
- private static String getToolsJarPath() {
- return System.getProperty("java.home") +
- "/../lib/tools.jar".replace("/", File.separator);
- }
}
--- a/jdk/test/com/sun/tools/attach/BasicTests.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/tools/attach/BasicTests.java Mon Feb 09 09:52:48 2015 -0800
@@ -80,8 +80,7 @@
// Need to add jdk/lib/tools.jar to classpath.
String classpath =
- System.getProperty("test.class.path", "") + File.pathSeparator +
- System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar";
+ System.getProperty("test.class.path", "");
String testClassDir = System.getProperty("test.classes", "") + sep;
// Argumenta : -classpath cp BasicTests$TestMain pid agent badagent redefineagent
--- a/jdk/test/com/sun/tools/attach/PermissionTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/tools/attach/PermissionTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -71,10 +71,8 @@
private static void runTests(long pid) throws Throwable {
final String sep = File.separator;
- // Need to add jdk/lib/tools.jar to classpath.
String classpath =
- System.getProperty("test.class.path", "") + File.pathSeparator +
- System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar";
+ System.getProperty("test.class.path", "");
String testSrc = System.getProperty("test.src", "") + sep;
// Use a policy that will NOT allow attach. Test will verify exception.
--- a/jdk/test/com/sun/tools/attach/ProviderTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/tools/attach/ProviderTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -68,11 +68,10 @@
String testClasses = System.getProperty("test.classes", "") + sep;
String jdkLib = System.getProperty("test.jdk", ".") + sep + "lib" + sep;
- // Need to add SimpleProvider.jar and tools.jar to classpath.
+ // Need to add SimpleProvider.jar to classpath.
String classpath =
testClassPath + File.pathSeparator +
- testClasses + "SimpleProvider.jar" + File.pathSeparator +
- jdkLib + "tools.jar";
+ testClasses + "SimpleProvider.jar";
String[] args = {
"-classpath",
--- a/jdk/test/com/sun/tools/attach/TempDirTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/com/sun/tools/attach/TempDirTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -120,10 +120,8 @@
private static void launchTests(long pid, Path clientTmpDir) throws Throwable {
final String sep = File.separator;
- // Need to add jdk/lib/tools.jar to classpath.
String classpath =
- System.getProperty("test.class.path", "") + File.pathSeparator +
- System.getProperty("test.jdk", ".") + sep + "lib" + sep + "tools.jar";
+ System.getProperty("test.class.path", "");
String[] tmpDirArg = null;
if (clientTmpDir != null) {
--- a/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java Mon Feb 09 09:52:48 2015 -0800
@@ -50,8 +50,9 @@
}
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
- ClassLoader loader = new URLClassLoader(((URLClassLoader) systemLoader).getURLs(),
- systemLoader.getParent());
+ URL testClassesURL = new File(System.getProperty("test.classes")).toURI().toURL();
+ ClassLoader loader = new URLClassLoader(new URL[] { testClassesURL } ,
+ systemLoader.getParent());
Class<? extends ObjectOutputStream> cl =
Class.forName(SubclassOfOOS.class.getName(), false,
loader).asSubclass(ObjectOutputStream.class);
--- a/jdk/test/java/io/Serializable/subclassGC/security.policy Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/io/Serializable/subclassGC/security.policy Mon Feb 09 09:52:48 2015 -0800
@@ -2,5 +2,7 @@
grant {
permission java.lang.RuntimePermission "createClassLoader";
permission java.lang.RuntimePermission "getClassLoader";
+ permission java.util.PropertyPermission "test.classes", "read";
+ permission java.io.FilePermission "<<ALL FILES>>", "read";
};
--- a/jdk/test/java/lang/instrument/IsModifiableClassAgent.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/lang/instrument/IsModifiableClassAgent.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,6 @@
/**
* @test
- * @ignore JDK-8068162
* @bug 6331574
* @summary test isModifiableClass
* @author Robert Field, Sun Microsystems
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/ServerSocket/AcceptInheritHandle.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8067105
+ * @summary Socket returned by ServerSocket.accept() is inherited by child process on Windows
+ * @author Chris Hegarty
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.channels.ServerSocketChannel;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+public class AcceptInheritHandle {
+
+ enum ServerSocketProducer {
+ JAVA_NET(() -> {
+ try {
+ return new ServerSocket(); }
+ catch(IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ }),
+ NIO_CHANNELS(() -> {
+ try {
+ return ServerSocketChannel.open().socket();
+ } catch (IOException x) {
+ throw new UncheckedIOException(x);
+ }
+ });
+
+ final Supplier<ServerSocket> supplier;
+ ServerSocketProducer(Supplier<ServerSocket> supplier) {
+ this.supplier = supplier;
+ }
+ Supplier<ServerSocket> supplier () { return supplier; }
+ }
+
+ static final String JAVA = System.getProperty("java.home")
+ + File.separator + "bin" + File.separator + "java";
+
+ static final String CLASSPATH = System.getProperty("java.class.path");
+
+ public static void main(String[] args) throws Exception {
+ if (args.length == 1)
+ server(ServerSocketProducer.valueOf(args[0]));
+ else
+ mainEntry();
+ }
+
+ static void mainEntry() throws Exception {
+ testJavaNetServerSocket();
+ testNioServerSocketChannel();
+ }
+
+ static void testJavaNetServerSocket() throws Exception {
+ test(ServerSocketProducer.JAVA_NET);
+ test(ServerSocketProducer.JAVA_NET, "-Djava.net.preferIPv4Stack=true");
+ }
+ static void testNioServerSocketChannel() throws Exception {
+ test(ServerSocketProducer.NIO_CHANNELS);
+ }
+
+ static void test(ServerSocketProducer ssp, String... sysProps) throws Exception {
+ System.out.println("\nStarting test for " + ssp.name());
+
+ List<String> commands = new ArrayList<>();
+ commands.add(JAVA);
+ for (String prop : sysProps)
+ commands.add(prop);
+ commands.add("-cp");
+ commands.add(CLASSPATH);
+ commands.add("AcceptInheritHandle");
+ commands.add(ssp.name());
+
+ System.out.println("Executing: "+ commands);
+ ProcessBuilder pb = new ProcessBuilder(commands);
+ pb.redirectError(ProcessBuilder.Redirect.INHERIT);
+ Process serverProcess = pb.start();
+ DataInputStream dis = new DataInputStream(serverProcess.getInputStream());
+
+ int port = dis.readInt();
+ System.out.println("Server process listening on " + port + ", connecting...");
+
+ Socket socket = new Socket("localhost", port);
+ String s = dis.readUTF();
+ System.out.println("Server process said " + s);
+
+ serverProcess.destroy();
+ serverProcess.waitFor(30, TimeUnit.SECONDS);
+ System.out.println("serverProcess exitCode:" + serverProcess.exitValue());
+
+ try {
+ socket.setSoTimeout(10 * 1000);
+ socket.getInputStream().read();
+ } catch (SocketTimeoutException x) {
+ // failed
+ throw new RuntimeException("Failed: should get reset, not " + x);
+ } catch (SocketException x) {
+ System.out.println("Expected:" + x);
+ }
+ }
+
+ static void server(ServerSocketProducer producer) throws Exception {
+ try (ServerSocket ss = producer.supplier().get()) {
+ ss.bind(new InetSocketAddress(0));
+ int port = ss.getLocalPort();
+ DataOutputStream dos = new DataOutputStream(System.out);
+ dos.writeInt(port);
+ dos.flush();
+
+ ss.accept(); // do not close
+
+ Runtime.getRuntime().exec("sleep 20");
+ Thread.sleep(3 * 1000);
+
+ dos.writeUTF("kill me!");
+ dos.flush();
+ Thread.sleep(30 * 1000);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/channels/FileLock/FileLockConstructor.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.file.StandardOpenOption;
+
+/*
+ * @test
+ * @bug 6880737
+ * @summary Test FileLock constructor parameter validation.
+ */
+public class FileLockConstructor {
+ public static void main(String[] args) throws IOException {
+ FileLock fileLock = null;
+ int failures = 0;
+
+ // null FileChannel
+ boolean exceptionThrown = false;
+ try {
+ fileLock = new FileLockSub((FileChannel)null, 0, 0, false);
+ } catch (NullPointerException npe) {
+ exceptionThrown = true;
+ }
+ if (!exceptionThrown) {
+ System.err.println("FileLock constructor did not throw NPE for null FileChannel");
+ failures++;
+ }
+
+ // null AsynchronousFileChannel
+ exceptionThrown = false;
+ try {
+ fileLock = new FileLockSub((AsynchronousFileChannel)null, 0, 0, true);
+ } catch (NullPointerException npe) {
+ exceptionThrown = true;
+ }
+ if (!exceptionThrown) {
+ System.err.println("FileLock constructor did not throw NPE for null AsynchronousFileChannel");
+ failures++;
+ }
+
+ // create temporary file
+ File tmpFile = File.createTempFile("FileLock", "tmp");
+ tmpFile.deleteOnExit();
+
+ // position and size preconditions
+ long[][] posAndSize = new long[][] {
+ {0, 42}, // valid
+ {-1, 42}, // invalid: position < 0
+ {0, -1}, // invalid: size < 0
+ {Long.MAX_VALUE, 1} // invalid: position + size < 0
+ };
+
+ // test position and size preconditions for FileChannel case
+ try (FileChannel syncChannel = FileChannel.open(tmpFile.toPath(),
+ StandardOpenOption.READ, StandardOpenOption.WRITE)) {
+
+ for (int i = 0; i < posAndSize.length; i++) {
+ boolean preconditionsHold = i == 0;
+ exceptionThrown = false;
+ try {
+ fileLock = new FileLockSub(syncChannel, posAndSize[i][0],
+ posAndSize[i][1], true);
+ } catch (IllegalArgumentException iae) {
+ exceptionThrown = true;
+ } catch (Exception e) {
+ System.err.println("Unexpected exception \"" + e + "\" caught"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for FileChannel variant");
+ failures++;
+ continue;
+ }
+ if (preconditionsHold && exceptionThrown) {
+ System.err.println("FileLock constructor incorrectly threw IAE"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for FileChannel variant");
+ failures++;
+ } else if (!preconditionsHold && !exceptionThrown) {
+ System.err.println("FileLock constructor did not throw IAE"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for FileChannel variant");
+ failures++;
+ }
+ }
+ }
+
+ // test position and size preconditions for AsynchronousFileChannel case
+ try (AsynchronousFileChannel asyncChannel
+ = AsynchronousFileChannel.open(tmpFile.toPath(),
+ StandardOpenOption.READ, StandardOpenOption.WRITE)) {
+ for (int i = 0; i < posAndSize.length; i++) {
+ boolean preconditionsHold = i == 0;
+ exceptionThrown = false;
+ try {
+ fileLock = new FileLockSub(asyncChannel, posAndSize[i][0],
+ posAndSize[i][1], true);
+ } catch (IllegalArgumentException iae) {
+ exceptionThrown = true;
+ } catch (Exception e) {
+ System.err.println("Unexpected exception \"" + e + "\" caught"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for AsynchronousFileChannel variant");
+ failures++;
+ continue;
+ }
+ if (preconditionsHold && exceptionThrown) {
+ System.err.println("FileLock constructor incorrectly threw IAE"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for AsynchronousFileChannel variant");
+ failures++;
+ } else if (!preconditionsHold && !exceptionThrown) {
+ System.err.println("FileLock constructor did not throw IAE"
+ + " for position " + posAndSize[i][0] + " and size "
+ + posAndSize[i][1] + " for AsynchronousFileChannel variant");
+ failures++;
+ }
+ }
+ }
+
+ if (failures > 0) {
+ throw new RuntimeException("Incurred " + failures +
+ " failures while testing FileLock.");
+ }
+ }
+}
+
+class FileLockSub extends FileLock {
+ FileLockSub(FileChannel channel, long position, long size, boolean shared) {
+ super(channel, position, size, shared);
+ }
+
+ FileLockSub(AsynchronousFileChannel channel, long position, long size,
+ boolean shared) {
+ super(channel, position, size, shared);
+ }
+
+ @Override
+ public boolean isValid() {
+ return false;
+ }
+
+ @Override
+ public void release() throws IOException {
+ // do nothing
+ }
+}
--- a/jdk/test/java/nio/file/Path/PathOps.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/nio/file/Path/PathOps.java Mon Feb 09 09:52:48 2015 -0800
@@ -22,7 +22,7 @@
*/
/* @test
- * @bug 4313887 6838333 6925932 7006126 8037945
+ * @bug 4313887 6838333 6925932 7006126 8037945 8072495
* @summary Unit test for java.nio.file.Path path operations
*/
@@ -516,7 +516,9 @@
.relativize("\\\\server\\share\\bar", "..\\bar")
.relativize("\\\\server\\share\\foo", "");
test("")
- .relativize("", "");
+ .relativize("", "")
+ .relativize("a", "a")
+ .relativize("a\\b\\c", "a\\b\\c");
// normalize
test("C:\\")
--- a/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/tck/java/time/TCKLocalDateTime.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -292,7 +292,8 @@
expected = LocalDateTime.now(Clock.system(zone));
test = LocalDateTime.now(zone);
}
- assertEquals(test, expected);
+ assertEquals(test.truncatedTo(ChronoUnit.SECONDS),
+ expected.truncatedTo(ChronoUnit.SECONDS));
}
//-----------------------------------------------------------------------
--- a/jdk/test/java/time/tck/java/time/TCKLocalTime.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/tck/java/time/TCKLocalTime.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -246,7 +246,8 @@
expected = LocalTime.now(Clock.system(zone));
test = LocalTime.now(zone);
}
- assertEquals(test, expected);
+ assertEquals(test.truncatedTo(ChronoUnit.SECONDS),
+ expected.truncatedTo(ChronoUnit.SECONDS));
}
//-----------------------------------------------------------------------
--- a/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/tck/java/time/TCKZonedDateTime.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -260,7 +260,8 @@
expected = ZonedDateTime.now(Clock.system(zone));
test = ZonedDateTime.now(zone);
}
- assertEquals(test, expected);
+ assertEquals(test.truncatedTo(ChronoUnit.SECONDS),
+ expected.truncatedTo(ChronoUnit.SECONDS));
}
//-----------------------------------------------------------------------
--- a/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/tck/java/time/chrono/TCKJapaneseEra.java Mon Feb 09 09:52:48 2015 -0800
@@ -59,6 +59,7 @@
import static java.time.temporal.ChronoField.ERA;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
import java.time.chrono.Era;
import java.time.chrono.JapaneseChronology;
@@ -69,7 +70,8 @@
import org.testng.annotations.Test;
/**
- * Test.
+ * Tests for JapaneseEra
+ * @bug 8068278
*/
@Test
public class TCKJapaneseEra {
@@ -84,6 +86,20 @@
};
}
+ @DataProvider(name = "InvalidJapaneseEras")
+ Object[][] data_of_invalid_eras() {
+ return new Object[][] {
+ {-2},
+ {-3},
+ {3},
+ {Integer.MIN_VALUE},
+ {Integer.MAX_VALUE},
+ };
+ }
+
+ //-----------------------------------------------------------------------
+ // JapaneseEra value test
+ //-----------------------------------------------------------------------
@Test(dataProvider="JapaneseEras")
public void test_valueOf(JapaneseEra era , String eraName, int eraValue) {
assertEquals(era.getValue(), eraValue);
@@ -118,4 +134,11 @@
}
}
+ //-----------------------------------------------------------------------
+ // JapaneseChronology.INSTANCE.eraOf invalid era test
+ //-----------------------------------------------------------------------
+ @Test(dataProvider="InvalidJapaneseEras", expectedExceptions=java.time.DateTimeException.class)
+ public void test_outofrange(int era) {
+ JapaneseChronology.INSTANCE.eraOf(era);
+ }
}
--- a/jdk/test/java/time/test/java/time/TestClock_System.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/test/java/time/TestClock_System.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -62,7 +62,9 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
+import java.lang.reflect.Field;
import java.time.Clock;
+import java.time.Instant;
import java.time.ZoneId;
import org.testng.annotations.Test;
@@ -87,4 +89,298 @@
assertEquals(test.toString(), "SystemClock[Europe/Paris]");
}
+ //-----------------------------------------------------------------------
+
+ private static String formatTime(String prefix, Instant time) {
+ return prefix + ": " + time + " - seconds: "
+ + time.getEpochSecond() + ", nanos: "
+ + time.getNano();
+ }
+
+ public void test_ClockResolution() {
+ Clock highestUTC = Clock.systemUTC();
+
+ Instant start = Instant.ofEpochMilli(System.currentTimeMillis());
+
+ try {
+ // smoke test
+ Instant system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+ Instant system2 = Instant.ofEpochMilli(System.currentTimeMillis());
+ Instant highest1 = highestUTC.instant();
+ Instant highest2 = highestUTC.instant();
+ System.out.println(formatTime("\nsystemUTC #1 ", system1));
+ System.out.println(formatTime("systemUTC #2 ", system2));
+ System.out.println(formatTime("highestResolutionUTC #1 ", highest1));
+ System.out.println(formatTime("highestResolutionUTC #2 ", highest2));
+
+ if (system2.isBefore(system1)) {
+ System.err.println("system2 is before system1!");
+ System.err.println(formatTime("\n\tsystem1", system1));
+ System.err.println(formatTime("\n\tsystem2", system2));
+ throw new RuntimeException("system2 is before system1!"
+ + formatTime("\n\tsystem1", system1)
+ + formatTime("\n\tsystem2", system2));
+ }
+ if (highest2.isBefore(highest1)) {
+ System.err.println("highest2 is before highest1!");
+ System.err.println(formatTime("\n\thighest1", system1));
+ System.err.println(formatTime("\n\tsystem2", highest2));
+ throw new RuntimeException("highest2 is before system1!"
+ + formatTime("\n\thighest1", system1)
+ + formatTime("\n\tsystem2", highest2));
+ }
+
+ // better test - but depends on implementation details.
+ // we're not rounding - so highest1 should be greater or equal to
+ // system1
+ system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+ highest1 = highestUTC.instant();
+
+ System.out.println(formatTime("\nsystemUTC ", system1));
+ System.out.println(formatTime("highestResolutionUTC ", highest1));
+
+ if (highest1.isBefore(system1)) {
+ System.err.println("highest1 is before system1!");
+ System.err.println(formatTime("\n\tsystem1", system1));
+ System.err.println(formatTime("\n\thighest1", highest1));
+ throw new RuntimeException("highest1 is before system1!"
+ + formatTime("\n\tsystem1", system1)
+ + formatTime("\n\thighest1", highest1));
+ }
+
+ int count=0;
+ // let's preheat the system a bit:
+ for (int i = 0; i < 1000 ; i++) {
+ system1 = Instant.ofEpochMilli(System.currentTimeMillis());
+ highest1 = highestUTC.instant();
+ final int sysnan = system1.getNano();
+ final int nanos = highest1.getNano();
+ if ((nanos % 1000000) > 0) {
+ count++; // we have micro seconds
+ }
+ if ((sysnan % 1000000) > 0) {
+ throw new RuntimeException("Expected only millisecconds "
+ + "precision for systemUTC, found "
+ + (sysnan % 1000000) + " remainder.");
+ }
+ }
+ System.out.println("\nNumber of time stamps which had better than"
+ + " millisecond precision: "+count+"/"+1000);
+ System.out.println(formatTime("\nsystemUTC ", system1));
+ System.out.println(formatTime("highestResolutionUTC ", highest1));
+ if (count == 0) {
+ System.err.println("Something is strange: no microsecond "
+ + "precision with highestResolutionUTC?");
+ throw new RuntimeException("Micro second preccision not reached");
+ }
+
+ // check again
+ if (highest1.isBefore(system1)) {
+ System.err.println("highest1 is before system1!");
+ System.err.println(formatTime("\n\tsystem1", system1));
+ System.err.println(formatTime("\n\thighest1", highest1));
+ throw new RuntimeException("highest1 is before system1!"
+ + formatTime("\n\tsystem1", system1)
+ + formatTime("\n\thighest1", highest1));
+ }
+
+ // leap of faith: ensure that highest1 is from within 10 secs of
+ // system1
+ if (highest1.toEpochMilli() != system1.toEpochMilli()) {
+ long delta = highest1.getEpochSecond() - system1.getEpochSecond();
+ if (delta > 10) {
+ throw new RuntimeException("Unexpected long delay between two clocks ("
+ + delta + " seconds)"
+ + formatTime("\n\t system1", system1)
+ + formatTime("\n\t highest1", highest1));
+
+ }
+ } else {
+ System.out.println("You won the lottery: the two dates are within 1 millisecond!\n");
+ }
+
+ } finally {
+ Instant stop = Instant.ofEpochMilli(System.currentTimeMillis());
+ if (start.isAfter(stop)) {
+ // This should not happen - but can (un)probably be observed
+ // when switching to summer time, or if another application
+ // is switching the system date...
+ System.err.println("Cannot test - date was setback: "
+ + formatTime("\n\tstarted at", start)
+ + formatTime("\n\tstopped at", stop) + "\n");
+ return; // will prevent exceptions from being propagated.
+ }
+ }
+ }
+
+ static final long MAX_OFFSET = 0x0100000000L;
+ static final long MIN_OFFSET = -MAX_OFFSET;
+
+ // A helper class to test that SystemClock correctly recomputes
+ // its offset.
+ static class SystemClockOffset {
+
+ static final int MILLIS_IN_SECOND = 1000;
+ static final int NANOS_IN_MILLI = 1000_000;
+ static final int NANOS_IN_MICRO = 1000;
+ static final int NANOS_IN_SECOND = 1000_000_000;
+
+ static final boolean verbose = true;
+ static final Clock systemUTC = Clock.systemUTC();
+ static final Field offsetField;
+
+ static {
+ try {
+ offsetField = Class.forName("java.time.Clock$SystemClock").getDeclaredField("offset");
+ offsetField.setAccessible(true);
+ } catch (ClassNotFoundException | NoSuchFieldException ex) {
+ throw new ExceptionInInitializerError(ex);
+ }
+ }
+
+ static enum Answer {
+
+ YES, // isOffLimit = YES: we must get -1
+ NO, // isOffLimit = NO: we must not not get -1
+ MAYBE // isOffLimit = MAYBE: we might get -1 or a valid adjustment.
+ };
+
+ static long distance(long one, long two) {
+ return one > two ? Math.subtractExact(one, two)
+ : Math.subtractExact(two, one);
+ }
+
+ static Answer isOffLimits(long before, long after, long offset) {
+ long relativeDistanceBefore = distance(before, offset);
+ long relativeDistanceAfter = distance(after, offset);
+ if (relativeDistanceBefore >= MAX_OFFSET && relativeDistanceAfter >= MAX_OFFSET) {
+ return Answer.YES;
+ }
+ if (relativeDistanceBefore < MAX_OFFSET && relativeDistanceAfter < MAX_OFFSET) {
+ if (relativeDistanceBefore == 0 || relativeDistanceAfter == 0) {
+ return Answer.MAYBE; // unlucky case where
+ }
+ return Answer.NO;
+ }
+ return Answer.MAYBE;
+ }
+
+ static void testWithOffset(String name, long offset)
+ throws IllegalAccessException {
+ testWithOffset(name, offset, systemUTC);
+ }
+
+ static void testWithOffset(String name, long offset, Clock clock)
+ throws IllegalAccessException {
+ offsetField.set(clock, offset);
+ long beforeMillis = System.currentTimeMillis();
+ final Instant instant = clock.instant();
+ long afterMillis = System.currentTimeMillis();
+ long actualOffset = offsetField.getLong(clock);
+ long instantMillis = instant.getEpochSecond() * MILLIS_IN_SECOND
+ + instant.getNano() / NANOS_IN_MILLI;
+ if (instantMillis < beforeMillis || instantMillis > afterMillis) {
+ throw new RuntimeException(name
+ + ": Invalid instant: " + instant
+ + " (~" + instantMillis + "ms)"
+ + " when time in millis is in ["
+ + beforeMillis + ", " + afterMillis
+ + "] and offset in seconds is " + offset);
+ }
+ Answer isOffLimits = isOffLimits(beforeMillis / MILLIS_IN_SECOND,
+ afterMillis / MILLIS_IN_SECOND, offset);
+ switch (isOffLimits) {
+ case YES:
+ if (actualOffset == offset) {
+ throw new RuntimeException(name
+ + ": offset was offlimit but was not recomputed "
+ + " when time in millis is in ["
+ + beforeMillis + ", " + afterMillis
+ + "] and offset in seconds was " + offset);
+ }
+ break;
+ case NO:
+ if (actualOffset != offset) {
+ throw new RuntimeException(name
+ + ": offset was not offlimit but was recomputed.");
+ }
+ break;
+ default:
+ break;
+ }
+ if (distance(actualOffset, instant.getEpochSecond()) >= MAX_OFFSET) {
+ throw new RuntimeException(name + ": Actual offset is too far off:"
+ + " offset=" + actualOffset
+ + "instant.seconds=" + instant.getEpochSecond());
+ }
+ long adjustment = (instant.getEpochSecond() - actualOffset) * NANOS_IN_SECOND
+ + instant.getNano();
+ validateAdjustment(name, actualOffset, beforeMillis, afterMillis, adjustment);
+ }
+
+ static void validateAdjustment(String name, long offset, long beforeMillis,
+ long afterMillis, long adjustment) {
+ System.out.println("Validating adjustment: " + adjustment);
+ long expectedMax = distance(offset, beforeMillis / MILLIS_IN_SECOND)
+ * NANOS_IN_SECOND
+ + (beforeMillis % MILLIS_IN_SECOND) * NANOS_IN_MILLI
+ + (afterMillis - beforeMillis + 1) * NANOS_IN_MILLI;
+ long absoluteAdjustment = distance(0, adjustment);
+ if (absoluteAdjustment > expectedMax) {
+ long adjSec = absoluteAdjustment / NANOS_IN_SECOND;
+ long adjMil = (absoluteAdjustment % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+ long adjMic = (absoluteAdjustment % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+ long adjNan = (absoluteAdjustment % NANOS_IN_MICRO);
+ long expSec = expectedMax / NANOS_IN_SECOND;
+ long expMil = (expectedMax % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+ long expMic = (expectedMax % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+ long expNan = (expectedMax % NANOS_IN_MICRO);
+ System.err.println("Excessive adjustment: " + adjSec + "s, "
+ + adjMil + "ms, " + adjMic + "mics, " + adjNan + "ns");
+ System.err.println("Epected max: " + expSec + "s, "
+ + expMil + "ms, " + expMic + "mics, " + expNan + "ns");
+
+ throw new RuntimeException(name
+ + ": Excessive adjustment: " + adjustment
+ + " when time in millis is in ["
+ + beforeMillis + ", " + afterMillis
+ + "] and offset in seconds is " + offset);
+ }
+ }
+ }
+
+ public void test_OffsetRegular() throws IllegalAccessException {
+ System.out.println("*** Testing regular cases ***");
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000",
+ System.currentTimeMillis()/1000);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - 1024",
+ System.currentTimeMillis()/1000 - 1024);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + 1024",
+ System.currentTimeMillis()/1000 + 1024);
+ }
+
+ public void test_OffsetLimits() throws IllegalAccessException {
+ System.out.println("*** Testing limits ***");
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET + 1",
+ System.currentTimeMillis()/1000 - MAX_OFFSET + 1);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET - 1",
+ System.currentTimeMillis()/1000 + MAX_OFFSET - 1);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET",
+ System.currentTimeMillis()/1000 - MAX_OFFSET);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET",
+ System.currentTimeMillis()/1000 + MAX_OFFSET);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET - 1024",
+ System.currentTimeMillis()/1000 - MAX_OFFSET - 1024);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET + 1024",
+ System.currentTimeMillis()/1000 + MAX_OFFSET + 1024);
+ SystemClockOffset.testWithOffset("0", 0);
+ SystemClockOffset.testWithOffset("-1", -1);
+ SystemClockOffset.testWithOffset("Integer.MAX_VALUE + System.currentTimeMillis()/1000",
+ ((long)Integer.MAX_VALUE) + System.currentTimeMillis()/1000);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Integer.MIN_VALUE",
+ System.currentTimeMillis()/1000 - Integer.MIN_VALUE);
+ SystemClockOffset.testWithOffset("Long.MAX_VALUE", Long.MAX_VALUE);
+ SystemClockOffset.testWithOffset("System.currentTimeMillis()/1000 - Long.MIN_VALUE",
+ (Long.MIN_VALUE + System.currentTimeMillis()/1000)*-1);
+ }
}
--- a/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/test/java/time/chrono/TestUmmAlQuraChronology.java Mon Feb 09 09:52:48 2015 -0800
@@ -30,6 +30,7 @@
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
@@ -71,6 +72,7 @@
/**
* Tests for the Umm alQura chronology and data.
* Note: The dates used for testing are just a sample of calendar data.
+ * @bug 8067800
*/
@Test
public class TestUmmAlQuraChronology {
@@ -530,6 +532,24 @@
assertEquals(date.isLeapYear(), leapyear);
}
+ // Data provider to verify that a given hijrah year is outside the range of supported years
+ // The values are dependent on the currently configured UmmAlQura calendar data
+ @DataProvider(name="OutOfRangeLeapYears")
+ Object[][] data_invalid_leapyears() {
+ return new Object[][] {
+ {1299},
+ {1601},
+ {Integer.MAX_VALUE},
+ {Integer.MIN_VALUE},
+ };
+ }
+
+ @Test(dataProvider="OutOfRangeLeapYears")
+ public void test_notLeapYears(int y) {
+ assertFalse(HijrahChronology.INSTANCE.isLeapYear(y), "Out of range leap year");
+ }
+
+
// Date samples to convert HijrahDate to LocalDate and vice versa
@DataProvider(name="samples")
Object[][] data_samples() {
--- a/jdk/test/java/time/test/java/util/TestFormatter.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/time/test/java/util/TestFormatter.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,7 @@
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalQueries;
import java.time.temporal.TemporalAccessor;
+import java.time.temporal.UnsupportedTemporalTypeException;
import java.util.*;
@@ -153,6 +154,44 @@
if (verbose) {
System.out.printf("%-24s : %s%n", getClassName(dt), out);
}
+
+ // expected usually comes from Calendar which only has milliseconds
+ // precision. So we're going to replace it's N:[nanos] stamp with
+ // the correct value for nanos.
+ if ((dt instanceof TemporalAccessor) && expected != null) {
+ try {
+ // Get millis & nanos from the dt
+ final TemporalAccessor ta = (TemporalAccessor) dt;
+ final int nanos = ta.get(ChronoField.NANO_OF_SECOND);
+ final int millis = ta.get(ChronoField.MILLI_OF_SECOND);
+ final String nanstr = String.valueOf(nanos);
+ final String mistr = String.valueOf(millis);
+
+ // Compute the value of the N:[nanos] field that we expect
+ // to find in 'out'
+ final StringBuilder sb = new StringBuilder();
+ sb.append("N:[");
+ for (int i=nanstr.length(); i<9; i++) {
+ sb.append('0');
+ }
+ sb.append(nanos).append("]");
+
+ // Compute the truncated value of N:[nanos] field that might
+ // be in 'expected' when expected was built from Calendar.
+ final StringBuilder sbm = new StringBuilder();
+ sbm.append("N:[");
+ for (int i=mistr.length(); i<3; i++) {
+ sbm.append('0');
+ }
+ sbm.append(mistr).append("000000]");
+
+ // if expected contains the truncated value, replace it with
+ // the complete value.
+ expected = expected.replace(sbm.toString(), sb.toString());
+ } catch (UnsupportedTemporalTypeException e) {
+ // nano seconds unsupported - nothing to do...
+ }
+ }
if (expected != null && !out.equals(expected)) {
System.out.printf("%-24s actual: %s%n FAILED; expected: %s%n",
getClassName(dt), out, expected);
--- a/jdk/test/java/util/Optional/Basic.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/util/Optional/Basic.java Mon Feb 09 09:52:48 2015 -0800
@@ -29,6 +29,7 @@
import java.util.NoSuchElementException;
import java.util.Optional;
+import java.util.stream.Stream;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
@@ -54,8 +55,8 @@
assertSame(null, empty.orElse(null));
RuntimeException orElse = new RuntimeException() { };
assertSame(Boolean.FALSE, empty.orElse(Boolean.FALSE));
- assertSame(null, empty.orElseGet(()-> null));
- assertSame(Boolean.FALSE, empty.orElseGet(()-> Boolean.FALSE));
+ assertSame(null, empty.orElseGet(() -> null));
+ assertSame(Boolean.FALSE, empty.orElseGet(() -> Boolean.FALSE));
}
@Test(expectedExceptions=NoSuchElementException.class)
@@ -104,15 +105,15 @@
try {
present.ifPresent(v -> { throw new ObscureException(); });
fail();
- } catch(ObscureException expected) {
+ } catch (ObscureException expected) {
}
assertSame(Boolean.TRUE, present.orElse(null));
assertSame(Boolean.TRUE, present.orElse(Boolean.FALSE));
assertSame(Boolean.TRUE, present.orElseGet(null));
- assertSame(Boolean.TRUE, present.orElseGet(()-> null));
- assertSame(Boolean.TRUE, present.orElseGet(()-> Boolean.FALSE));
- assertSame(Boolean.TRUE, present.<RuntimeException>orElseThrow( null));
+ assertSame(Boolean.TRUE, present.orElseGet(() -> null));
+ assertSame(Boolean.TRUE, present.orElseGet(() -> Boolean.FALSE));
+ assertSame(Boolean.TRUE, present.<RuntimeException>orElseThrow(null));
assertSame(Boolean.TRUE, present.<RuntimeException>orElseThrow(ObscureException::new));
}
@@ -226,6 +227,26 @@
assertSame(l, fixture);
}
+ @Test(groups = "unit")
+ public void testStream() {
+ {
+ Stream<String> s = Optional.<String>empty().stream();
+ assertFalse(s.isParallel());
+
+ Object[] es = s.toArray();
+ assertEquals(es.length, 0);
+ }
+
+ {
+ Stream<String> s = Optional.of("Duke").stream();
+ assertFalse(s.isParallel());
+
+ String[] es = s.toArray(String[]::new);
+ assertEquals(es.length, 1);
+ assertEquals(es[0], "Duke");
+ }
+ }
+
private static class ObscureException extends RuntimeException {
}
--- a/jdk/test/java/util/Optional/BasicDouble.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/util/Optional/BasicDouble.java Mon Feb 09 09:52:48 2015 -0800
@@ -29,6 +29,7 @@
import java.util.NoSuchElementException;
import java.util.OptionalDouble;
+import java.util.stream.DoubleStream;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
@@ -109,6 +110,26 @@
assertEquals(1.0, present.<RuntimeException>orElseThrow(ObscureException::new));
}
+ @Test(groups = "unit")
+ public void testStream() {
+ {
+ DoubleStream s = OptionalDouble.empty().stream();
+ assertFalse(s.isParallel());
+
+ double[] es = s.toArray();
+ assertEquals(es.length, 0);
+ }
+
+ {
+ DoubleStream s = OptionalDouble.of(42.0).stream();
+ assertFalse(s.isParallel());
+
+ double[] es = s.toArray();
+ assertEquals(es.length, 1);
+ assertEquals(es[0], 42.0);
+ }
+ }
+
private static class ObscureException extends RuntimeException {
}
--- a/jdk/test/java/util/Optional/BasicInt.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/util/Optional/BasicInt.java Mon Feb 09 09:52:48 2015 -0800
@@ -29,6 +29,7 @@
import java.util.NoSuchElementException;
import java.util.OptionalInt;
+import java.util.stream.IntStream;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
@@ -53,36 +54,36 @@
assertEquals(2, empty.orElseGet(()-> 2));
}
- @Test(expectedExceptions=NoSuchElementException.class)
- public void testEmptyGet() {
- OptionalInt empty = OptionalInt.empty();
+ @Test(expectedExceptions=NoSuchElementException.class)
+ public void testEmptyGet() {
+ OptionalInt empty = OptionalInt.empty();
- int got = empty.getAsInt();
- }
+ int got = empty.getAsInt();
+ }
- @Test(expectedExceptions=NullPointerException.class)
- public void testEmptyOrElseGetNull() {
- OptionalInt empty = OptionalInt.empty();
+ @Test(expectedExceptions=NullPointerException.class)
+ public void testEmptyOrElseGetNull() {
+ OptionalInt empty = OptionalInt.empty();
- int got = empty.orElseGet(null);
- }
+ int got = empty.orElseGet(null);
+ }
- @Test(expectedExceptions=NullPointerException.class)
- public void testEmptyOrElseThrowNull() throws Throwable {
- OptionalInt empty = OptionalInt.empty();
+ @Test(expectedExceptions=NullPointerException.class)
+ public void testEmptyOrElseThrowNull() throws Throwable {
+ OptionalInt empty = OptionalInt.empty();
- int got = empty.orElseThrow(null);
- }
+ int got = empty.orElseThrow(null);
+ }
- @Test(expectedExceptions=ObscureException.class)
- public void testEmptyOrElseThrow() throws Exception {
- OptionalInt empty = OptionalInt.empty();
+ @Test(expectedExceptions=ObscureException.class)
+ public void testEmptyOrElseThrow() throws Exception {
+ OptionalInt empty = OptionalInt.empty();
- int got = empty.orElseThrow(ObscureException::new);
- }
+ int got = empty.orElseThrow(ObscureException::new);
+ }
- @Test(groups = "unit")
- public void testPresent() {
+ @Test(groups = "unit")
+ public void testPresent() {
OptionalInt empty = OptionalInt.empty();
OptionalInt present = OptionalInt.of(1);
@@ -109,6 +110,26 @@
assertEquals(1, present.<RuntimeException>orElseThrow(ObscureException::new));
}
+ @Test(groups = "unit")
+ public void testStream() {
+ {
+ IntStream s = OptionalInt.empty().stream();
+ assertFalse(s.isParallel());
+
+ int[] es = s.toArray();
+ assertEquals(es.length, 0);
+ }
+
+ {
+ IntStream s = OptionalInt.of(42).stream();
+ assertFalse(s.isParallel());
+
+ int[] es = OptionalInt.of(42).stream().toArray();
+ assertEquals(es.length, 1);
+ assertEquals(es[0], 42);
+ }
+ }
+
private static class ObscureException extends RuntimeException {
}
--- a/jdk/test/java/util/Optional/BasicLong.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/util/Optional/BasicLong.java Mon Feb 09 09:52:48 2015 -0800
@@ -29,6 +29,7 @@
import java.util.NoSuchElementException;
import java.util.OptionalLong;
+import java.util.stream.LongStream;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
@@ -109,6 +110,24 @@
assertEquals(1, present.<RuntimeException>orElseThrow(ObscureException::new));
}
+ @Test(groups = "unit")
+ public void testStream() {
+ {
+ LongStream s = OptionalLong.empty().stream();
+
+ long[] es = s.toArray();
+ assertEquals(es.length, 0);
+ }
+
+ {
+ LongStream s = OptionalLong.of(42L).stream();
+
+ long[] es = s.toArray();
+ assertEquals(es.length, 1);
+ assertEquals(es[0], 42L);
+ }
+ }
+
private static class ObscureException extends RuntimeException {
}
--- a/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/java/util/concurrent/CompletableFuture/ThenComposeExceptionTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -36,7 +36,7 @@
/**
* @test
- * @bug 8068432
+ * @bug 8068432 8072030
* @run testng ThenComposeExceptionTest
* @summary Test that CompletableFuture.thenCompose works correctly if the
* composing future completes exceptionally
@@ -92,7 +92,8 @@
Assert.assertNotSame(f_thenCompose, fe, "Composed CompletableFuture returned directly");
AtomicReference<Throwable> eOnWhenComplete = new AtomicReference<>();
- f_thenCompose.whenComplete((r, e) -> eOnWhenComplete.set(e));
+ CompletableFuture<String> f_whenComplete = f_thenCompose.
+ whenComplete((r, e) -> eOnWhenComplete.set(e));
afterAction.accept(fe);
@@ -103,10 +104,20 @@
catch (Throwable t) {
eOnJoined = t;
}
-
- Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException,
- "Incorrect exception reported on whenComplete");
Assert.assertTrue(eOnJoined instanceof CompletionException,
- "Incorrect exception reported when joined");
+ "Incorrect exception reported when joined on thenCompose: " + eOnJoined);
+
+ // Need to wait for f_whenComplete to complete to avoid
+ // race condition when updating eOnWhenComplete
+ eOnJoined = null;
+ try {
+ f_whenComplete.join();
+ } catch (Throwable t) {
+ eOnJoined = t;
+ }
+ Assert.assertTrue(eOnJoined instanceof CompletionException,
+ "Incorrect exception reported when joined on whenComplete: " + eOnJoined);
+ Assert.assertTrue(eOnWhenComplete.get() instanceof CompletionException,
+ "Incorrect exception passed to whenComplete: " + eOnWhenComplete.get());
}
-}
+}
\ No newline at end of file
--- a/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/lib/testlibrary/jdk/testlibrary/SimpleSSLContext.java Mon Feb 09 09:52:48 2015 -0800
@@ -56,7 +56,7 @@
*/
public SimpleSSLContext () throws IOException {
String paths = System.getProperty("test.src.path");
- StringTokenizer st = new StringTokenizer(paths,":");
+ StringTokenizer st = new StringTokenizer(paths, File.pathSeparator);
boolean securityExceptions = false;
while (st.hasMoreTokens()) {
String path = st.nextToken();
--- a/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/management/jmxremote/bootstrap/CustomLauncherTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -145,13 +145,7 @@
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
"-cp",
- TEST_CLASSPATH +
- File.pathSeparator +
- TEST_JDK +
- File.separator +
- "lib" +
- File.separator +
- "tools.jar",
+ TEST_CLASSPATH,
"TestManager",
String.valueOf(serverPrc.getPid()),
port.get(),
--- a/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/management/jmxremote/bootstrap/LocalManagementTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -132,13 +132,7 @@
ProcessBuilder client = ProcessTools.createJavaProcessBuilder(
"-cp",
- TEST_CLASSPATH +
- File.pathSeparator +
- TEST_JDK +
- File.separator +
- "lib" +
- File.separator +
- "tools.jar",
+ TEST_CLASSPATH,
"TestManager",
String.valueOf(serverPrc.getPid()),
port.get(),
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/misc/VM/GetNanoTimeAdjustment.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.util.Objects;
+import sun.misc.VM;
+
+/**
+ * @test
+ * @bug 8068730
+ * @summary tests that VM.getgetNanoTimeAdjustment() works as expected.
+ * @run main GetNanoTimeAdjustment
+ * @author danielfuchs
+ */
+public class GetNanoTimeAdjustment {
+
+ static final int MILLIS_IN_SECOND = 1000;
+ static final int NANOS_IN_MILLI = 1000_000;
+ static final int NANOS_IN_MICRO = 1000;
+ static final int NANOS_IN_SECOND = 1000_000_000;
+
+ static final boolean verbose = true;
+
+ static final class TestAssertException extends RuntimeException {
+ TestAssertException(String msg) { super(msg); }
+ }
+
+ private static void assertEquals(long expected, long received, String msg) {
+ if (expected != received) {
+ throw new TestAssertException("Unexpected result for " + msg
+ + ".\n\texpected: " + expected
+ + "\n\tactual: " + received);
+ } else if (verbose) {
+ System.out.println("Got expected " + msg + ": " + received);
+ }
+ }
+
+ private static void assertEquals(Object expected, Object received, String msg) {
+ if (!Objects.equals(expected, received)) {
+ throw new TestAssertException("Unexpected result for " + msg
+ + ".\n\texpected: " + expected
+ + "\n\tactual: " + received);
+ } else if (verbose) {
+ System.out.println("Got expected " + msg + ": " + received);
+ }
+ }
+
+ static final long MAX_OFFSET = 0x0100000000L;
+ static final long MIN_OFFSET = -MAX_OFFSET;
+ static enum Answer {
+ YES, // isOffLimit = YES: we must get -1
+ NO, // isOffLimit = NO: we must not not get -1
+ MAYBE // isOffLimit = MAYBE: we might get -1 or a valid adjustment.
+ };
+ static long distance(long one, long two) {
+ return one > two ? Math.subtractExact(one, two)
+ : Math.subtractExact(two, one);
+ }
+
+
+ static Answer isOffLimits(long before, long after, long offset) {
+ long relativeDistanceBefore = distance(before, offset);
+ long relativeDistanceAfter = distance(after, offset);
+ if (relativeDistanceBefore >= MAX_OFFSET && relativeDistanceAfter >= MAX_OFFSET) {
+ return Answer.YES;
+ }
+ if (relativeDistanceBefore < MAX_OFFSET && relativeDistanceAfter < MAX_OFFSET) {
+ if (relativeDistanceBefore == 0 || relativeDistanceAfter == 0) {
+ return Answer.MAYBE; // unlucky case where
+ }
+ return Answer.NO;
+ }
+ return Answer.MAYBE;
+ }
+
+ static void testWithOffset(String name, long offset) {
+ System.out.println("Testing with offset: " + name);
+ long beforeMillis = System.currentTimeMillis();
+ long adjustment = VM.getNanoTimeAdjustment(offset);
+ long afterMillis = System.currentTimeMillis();
+
+ if (offset >= beforeMillis/MILLIS_IN_SECOND
+ && offset <= afterMillis/MILLIS_IN_SECOND) {
+ if (adjustment == -1) {
+ // it's possible that we have fallen in the unlucky case
+ // where -1 was the genuine result. let's go backward a bit.
+ offset = offset - 10;
+ beforeMillis = System.currentTimeMillis();
+ adjustment = VM.getNanoTimeAdjustment(offset);
+ afterMillis = System.currentTimeMillis();
+ if (adjustment == -1) {
+ throw new RuntimeException(name + ": VM says " + offset
+ + " secs is too far off, "
+ + " when time in seconds is in ["
+ + beforeMillis/MILLIS_IN_SECOND + ", "
+ + afterMillis/MILLIS_IN_SECOND
+ + "]");
+ }
+ }
+ }
+
+ Answer isOffLimit = isOffLimits(beforeMillis/MILLIS_IN_SECOND,
+ afterMillis/MILLIS_IN_SECOND, offset);
+ switch (isOffLimit) {
+ case YES:
+ if (adjustment != -1) {
+ throw new RuntimeException(name
+ + ": VM should have returned -1 for "
+ + offset
+ + " when time in seconds is in ["
+ + beforeMillis/MILLIS_IN_SECOND + ", "
+ + afterMillis/MILLIS_IN_SECOND + "]");
+ }
+ System.out.println("Got expected exception value: " + adjustment);
+ break;
+ case NO:
+ if (adjustment == -1) {
+ throw new RuntimeException(name
+ + "VM says " + offset
+ + " secs is too far off, "
+ + " when time in seconds is in ["
+ + beforeMillis/MILLIS_IN_SECOND + ", "
+ + afterMillis/MILLIS_IN_SECOND
+ + "]");
+ }
+ break;
+ case MAYBE:
+ System.out.println("Adjustment: " + adjustment);
+ System.out.println("Can't assert for -1 with offset "
+ + offset + "(" + name + ")"
+ + " when time in seconds is in ["
+ + beforeMillis/MILLIS_IN_SECOND + ", "
+ + afterMillis/MILLIS_IN_SECOND
+ + "]");
+ // not conclusive
+ }
+
+ if (isOffLimit == Answer.NO || adjustment != -1) {
+ System.out.println("Validating adjustment: " + adjustment);
+ long expectedMax = distance(offset, beforeMillis/MILLIS_IN_SECOND)
+ * NANOS_IN_SECOND
+ + (beforeMillis % MILLIS_IN_SECOND) * NANOS_IN_MILLI
+ + (afterMillis - beforeMillis + 1) * NANOS_IN_MILLI;
+ long absoluteAdjustment = distance(0, adjustment);
+ if (absoluteAdjustment > expectedMax) {
+ long adjSec = absoluteAdjustment / NANOS_IN_SECOND;
+ long adjMil = (absoluteAdjustment % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+ long adjMic = (absoluteAdjustment % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+ long adjNan = (absoluteAdjustment % NANOS_IN_MICRO);
+ long expSec = expectedMax / NANOS_IN_SECOND;
+ long expMil = (expectedMax % NANOS_IN_SECOND) / NANOS_IN_MILLI;
+ long expMic = (expectedMax % NANOS_IN_MILLI) / NANOS_IN_MICRO;
+ long expNan = (expectedMax % NANOS_IN_MICRO);
+ System.err.println("Excessive adjustment: " + adjSec + "s, "
+ + adjMil + "ms, " + adjMic + "mics, " + adjNan + "ns");
+ System.err.println("Epected max: " + expSec + "s, "
+ + expMil + "ms, " + expMic + "mics, " + expNan + "ns");
+
+ throw new RuntimeException(name
+ + ": Excessive adjustment: " + adjustment
+ + " when time in millis is in ["
+ + beforeMillis + ", " + afterMillis
+ + "] and offset in seconds is " + offset);
+ }
+ }
+
+ }
+
+ static void regular() {
+ System.out.println("*** Testing regular cases ***");
+ final long start = System.currentTimeMillis();
+ long offset = start/1000;
+ long adjustment = VM.getNanoTimeAdjustment(offset);
+ if (start != offset*1000) {
+ if (adjustment == -1) {
+ throw new RuntimeException("VM says " + offset
+ + " secs is too far off, but time millis is "
+ + System.currentTimeMillis());
+ }
+ }
+ if (adjustment == -1) {
+ offset = System.currentTimeMillis()/1000 - 1024;
+ adjustment = VM.getNanoTimeAdjustment(offset);
+ if (adjustment == -1) {
+ throw new RuntimeException("VM says " + offset
+ + " secs is too far off, but time millis is "
+ + System.currentTimeMillis());
+ }
+ }
+ if (adjustment > (start/1000 - offset + 20)*NANOS_IN_SECOND) {
+ throw new RuntimeException("Excessive adjustment: " + adjustment);
+ }
+ testWithOffset("System.currentTimeMillis()/1000",
+ System.currentTimeMillis()/1000);
+ testWithOffset("System.currentTimeMillis()/1000 - 1024",
+ System.currentTimeMillis()/1000 - 1024);
+ testWithOffset("System.currentTimeMillis()/1000 + 1024",
+ System.currentTimeMillis()/1000 + 1024);
+ }
+
+ static void testLimits() {
+ System.out.println("*** Testing limits ***");
+ testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET + 1",
+ System.currentTimeMillis()/1000 - MAX_OFFSET + 1);
+ testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET - 1",
+ System.currentTimeMillis()/1000 + MAX_OFFSET - 1);
+ testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET",
+ System.currentTimeMillis()/1000 - MAX_OFFSET);
+ testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET",
+ System.currentTimeMillis()/1000 + MAX_OFFSET);
+ testWithOffset("System.currentTimeMillis()/1000 - MAX_OFFSET - 1024",
+ System.currentTimeMillis()/1000 - MAX_OFFSET - 1024);
+ testWithOffset("System.currentTimeMillis()/1000 + MAX_OFFSET + 1024",
+ System.currentTimeMillis()/1000 + MAX_OFFSET + 1024);
+ testWithOffset("0", 0);
+ testWithOffset("-1", -1);
+ testWithOffset("Integer.MAX_VALUE + System.currentTimeMillis()/1000",
+ ((long)Integer.MAX_VALUE) + System.currentTimeMillis()/1000);
+ testWithOffset("System.currentTimeMillis()/1000 - Integer.MIN_VALUE",
+ System.currentTimeMillis()/1000 - Integer.MIN_VALUE);
+ testWithOffset("Long.MAX_VALUE", Long.MAX_VALUE);
+ testWithOffset("System.currentTimeMillis()/1000 - Long.MIN_VALUE",
+ (Long.MIN_VALUE + System.currentTimeMillis()/1000)*-1);
+ }
+
+ public static void main(String[] args) throws Exception {
+ regular();
+ testLimits();
+ }
+
+}
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION Mon Feb 09 09:52:48 2015 -0800
@@ -21,4 +21,4 @@
# or visit www.oracle.com if you need additional information or have any
# questions.
#
-tzdata2014j
+tzdata2015a
--- a/jdk/test/sun/util/calendar/zi/tzdata/antarctica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/antarctica Mon Feb 09 09:52:48 2015 -0800
@@ -70,8 +70,8 @@
Rule ChileAQ 2010 only - Apr Sun>=1 3:00u 0 -
Rule ChileAQ 2011 only - May Sun>=2 3:00u 0 -
Rule ChileAQ 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule ChileAQ 2012 max - Apr Sun>=23 3:00u 0 -
-Rule ChileAQ 2012 max - Sep Sun>=2 4:00u 1:00 S
+Rule ChileAQ 2012 2015 - Apr Sun>=23 3:00u 0 -
+Rule ChileAQ 2012 2014 - Sep Sun>=2 4:00u 1:00 S
# Argentina - year-round bases
# Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
@@ -377,9 +377,10 @@
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Palmer 0 - zzz 1965
- -4:00 ArgAQ AR%sT 1969 Oct 5
+ -4:00 ArgAQ AR%sT 1969 Oct 5
-3:00 ArgAQ AR%sT 1982 May
- -4:00 ChileAQ CL%sT
+ -4:00 ChileAQ CL%sT 2015 Apr 26 3:00u
+ -3:00 - CLT
#
#
# McMurdo Station, Ross Island, since 1955-12
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia Mon Feb 09 09:52:48 2015 -0800
@@ -168,10 +168,7 @@
4:00 Azer AZ%sT
# Bahrain
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Bahrain 3:22:20 - LMT 1920 # Manamah
- 4:00 - GST 1972 Jun
- 3:00 - AST
+# See Asia/Qatar.
# Bangladesh
# From Alexander Krivenyshev (2009-05-13):
@@ -1754,9 +1751,7 @@
###############################################################################
# Kuwait
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Kuwait 3:11:56 - LMT 1950
- 3:00 - AST
+# See Asia/Riyadh.
# Laos
# See Asia/Bangkok.
@@ -1977,12 +1972,7 @@
5:45 - NPT # Nepal Time
# Oman
-
-# Milne says 3:54:24 was the meridian of the Muscat Tidal Observatory.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Muscat 3:54:24 - LMT 1920
- 4:00 - GST
+# See Asia/Dubai.
# Pakistan
@@ -2476,6 +2466,7 @@
Zone Asia/Qatar 3:26:08 - LMT 1920 # Al Dawhah / Doha
4:00 - GST 1972 Jun
3:00 - AST
+Link Asia/Qatar Asia/Bahrain
# Saudi Arabia
#
@@ -2502,6 +2493,8 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Riyadh 3:06:52 - LMT 1947 Mar 14
3:00 - AST
+Link Asia/Riyadh Asia/Aden # Yemen
+Link Asia/Riyadh Asia/Kuwait
# Singapore
# taken from Mok Ly Yng (2003-10-30)
@@ -2790,6 +2783,7 @@
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Dubai 3:41:12 - LMT 1920
4:00 - GST
+Link Asia/Dubai Asia/Muscat # Oman
# Uzbekistan
# Byalokoz 1919 says Uzbekistan was 4:27:53.
@@ -2874,10 +2868,4 @@
7:00 - ICT
# Yemen
-
-# Milne says 2:59:54 was the meridian of the saluting battery at Aden,
-# and that Yemen was at 1:55:56, the meridian of the Hagia Sophia.
-
-# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Asia/Aden 2:59:54 - LMT 1950
- 3:00 - AST
+# See Asia/Riyadh.
--- a/jdk/test/sun/util/calendar/zi/tzdata/backward Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/backward Mon Feb 09 09:52:48 2015 -0800
@@ -28,7 +28,7 @@
# and their old names. Many names changed in late 1993.
# Link TARGET LINK-NAME
-Link Africa/Asmara Africa/Asmera
+Link Africa/Nairobi Africa/Asmera
Link Africa/Abidjan Africa/Timbuktu
Link America/Argentina/Catamarca America/Argentina/ComodRivadavia
Link America/Adak America/Atka
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe Mon Feb 09 09:52:48 2015 -0800
@@ -1430,35 +1430,32 @@
# might be a reference to the Julian calendar as opposed to Gregorian, or it
# might mean something else (???).
#
-# From Paul Eggert (2006-03-22):
-# The Iceland Almanak, Shanks & Pottenger, and Whitman disagree on many points.
-# We go with the Almanak, except for one claim from Shanks & Pottenger, namely
-# that Reykavik was 21W57 from 1837 to 1908, local mean time before that.
+# From Paul Eggert (2014-11-22):
+# The information below is taken from the 1988 Almanak; see
+# http://www.almanak.hi.is/klukkan.html
#
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
-Rule Iceland 1917 1918 - Feb 19 23:00 1:00 S
+Rule Iceland 1917 1919 - Feb 19 23:00 1:00 S
Rule Iceland 1917 only - Oct 21 1:00 0 -
-Rule Iceland 1918 only - Nov 16 1:00 0 -
+Rule Iceland 1918 1919 - Nov 16 1:00 0 -
+Rule Iceland 1921 only - Mar 19 23:00 1:00 S
+Rule Iceland 1921 only - Jun 23 1:00 0 -
Rule Iceland 1939 only - Apr 29 23:00 1:00 S
-Rule Iceland 1939 only - Nov 29 2:00 0 -
+Rule Iceland 1939 only - Oct 29 2:00 0 -
Rule Iceland 1940 only - Feb 25 2:00 1:00 S
-Rule Iceland 1940 only - Nov 3 2:00 0 -
-Rule Iceland 1941 only - Mar 2 1:00s 1:00 S
-Rule Iceland 1941 only - Nov 2 1:00s 0 -
-Rule Iceland 1942 only - Mar 8 1:00s 1:00 S
-Rule Iceland 1942 only - Oct 25 1:00s 0 -
+Rule Iceland 1940 1941 - Nov Sun>=2 1:00s 0 -
+Rule Iceland 1941 1942 - Mar Sun>=2 1:00s 1:00 S
# 1943-1946 - first Sunday in March until first Sunday in winter
Rule Iceland 1943 1946 - Mar Sun>=1 1:00s 1:00 S
-Rule Iceland 1943 1948 - Oct Sun>=22 1:00s 0 -
+Rule Iceland 1942 1948 - Oct Sun>=22 1:00s 0 -
# 1947-1967 - first Sunday in April until first Sunday in winter
Rule Iceland 1947 1967 - Apr Sun>=1 1:00s 1:00 S
-# 1949 Oct transition delayed by 1 week
+# 1949 and 1967 Oct transitions delayed by 1 week
Rule Iceland 1949 only - Oct 30 1:00s 0 -
Rule Iceland 1950 1966 - Oct Sun>=22 1:00s 0 -
Rule Iceland 1967 only - Oct 29 1:00s 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
-Zone Atlantic/Reykjavik -1:27:24 - LMT 1837
- -1:27:48 - RMT 1908 # Reykjavik Mean Time?
+Zone Atlantic/Reykjavik -1:28 - LMT 1908
-1:00 Iceland IS%sT 1968 Apr 7 1:00s
0:00 - GMT
--- a/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/leapseconds Mon Feb 09 09:52:48 2015 -0800
@@ -77,3 +77,7 @@
Leap 2005 Dec 31 23:59:60 + S
Leap 2008 Dec 31 23:59:60 + S
Leap 2012 Jun 30 23:59:60 + S
+Leap 2015 Jun 30 23:59:60 + S
+
+# Updated through IERS Bulletin C49
+# File expires on: 28 December 2015
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica Mon Feb 09 09:52:48 2015 -0800
@@ -147,7 +147,7 @@
Rule US 1918 1919 - Oct lastSun 2:00 0 S
Rule US 1942 only - Feb 9 2:00 1:00 W # War
Rule US 1945 only - Aug 14 23:00u 1:00 P # Peace
-Rule US 1945 only - Sep 30 2:00 0 S
+Rule US 1945 only - Sep lastSun 2:00 0 S
Rule US 1967 2006 - Oct lastSun 2:00 0 S
Rule US 1967 1973 - Apr lastSun 2:00 1:00 D
Rule US 1974 only - Jan 6 2:00 1:00 D
@@ -2147,11 +2147,11 @@
# Mexico
-# From Paul Eggert (2001-03-05):
+# From Paul Eggert (2014-12-07):
# The Investigation and Analysis Service of the
# Mexican Library of Congress (MLoC) has published a
# history of Mexican local time (in Spanish)
-# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
+# http://www.diputados.gob.mx/bibliot/publica/inveyana/polisoc/horver/index.htm
#
# Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
# (In all cases we go with the MLoC.)
@@ -2320,6 +2320,24 @@
# efecto desde las dos horas del segundo domingo de marzo y concluirá a
# las dos horas del primer domingo de noviembre.
+# From Steffen Thorsen (2014-12-08), translated by Gwillim Law:
+# The Mexican state of Quintana Roo will likely change to EST in 2015.
+#
+# http://www.unioncancun.mx/articulo/2014/12/04/medio-ambiente/congreso-aprueba-una-hora-mas-de-sol-en-qroo
+# "With this change, the time conflict that has existed between the municipios
+# of Quintana Roo and the municipio of Felipe Carrillo Puerto may come to an
+# end. The latter declared itself in rebellion 15 years ago when a time change
+# was initiated in Mexico, and since then it has refused to change its time
+# zone along with the rest of the country."
+#
+# From Steffen Thorsen (2015-01-14), translated by Gwillim Law:
+# http://sipse.com/novedades/confirman-aplicacion-de-nueva-zona-horaria-para-quintana-roo-132331.html
+# "...the new time zone will come into effect at two o'clock on the first Sunday
+# of February, when we will have to advance the clock one hour from its current
+# time..."
+#
+# Also, the new zone will not use DST.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Mexico 1939 only - Feb 5 0:00 1:00 D
Rule Mexico 1939 only - Jun 25 0:00 0 S
@@ -2340,7 +2358,8 @@
Zone America/Cancun -5:47:04 - LMT 1922 Jan 1 0:12:56
-6:00 - CST 1981 Dec 23
-5:00 Mexico E%sT 1998 Aug 2 2:00
- -6:00 Mexico C%sT
+ -6:00 Mexico C%sT 2015 Feb 1 2:00
+ -5:00 - EST
# Campeche, Yucatán; represented by Mérida
Zone America/Merida -5:58:28 - LMT 1922 Jan 1 0:01:32
-6:00 - CST 1981 Dec 23
--- a/jdk/test/sun/util/calendar/zi/tzdata/southamerica Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/southamerica Mon Feb 09 09:52:48 2015 -0800
@@ -1229,6 +1229,11 @@
# DST Start: first Saturday of September 2014 (Sun 07 Sep 2014 04:00 UTC)
# http://www.diariooficial.interior.gob.cl//media/2014/02/19/do-20140219.pdf
+# From Juan Correa (2015-01-28):
+# ... today the Ministry of Energy announced that Chile will drop DST, will keep
+# "summer time" (UTC -3 / UTC -5) all year round....
+# http://www.minenergia.cl/ministerio/noticias/generales/ministerio-de-energia-anuncia.html
+
# NOTE: ChileAQ rules for Antarctic bases are stored separately in the
# 'antarctica' file.
@@ -1270,8 +1275,8 @@
Rule Chile 2010 only - Apr Sun>=1 3:00u 0 -
Rule Chile 2011 only - May Sun>=2 3:00u 0 -
Rule Chile 2011 only - Aug Sun>=16 4:00u 1:00 S
-Rule Chile 2012 max - Apr Sun>=23 3:00u 0 -
-Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S
+Rule Chile 2012 2015 - Apr Sun>=23 3:00u 0 -
+Rule Chile 2012 2014 - Sep Sun>=2 4:00u 1:00 S
# IATA SSIM anomalies: (1992-02) says 1992-03-14;
# (1996-09) says 1998-03-08. Ignore these.
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@@ -1282,11 +1287,13 @@
-4:00 - CLT 1919 Jul 1 # Chile Time
-4:42:46 - SMT 1927 Sep 1 # Santiago Mean Time
-5:00 Chile CL%sT 1947 May 22 # Chile Time
- -4:00 Chile CL%sT
+ -4:00 Chile CL%sT 2015 Apr 26 3:00u
+ -3:00 - CLT
Zone Pacific/Easter -7:17:44 - LMT 1890
-7:17:28 - EMT 1932 Sep # Easter Mean Time
- -7:00 Chile EAS%sT 1982 Mar 13 21:00 # Easter Time
- -6:00 Chile EAS%sT
+ -7:00 Chile EAS%sT 1982 Mar 13 3:00u # Easter Time
+ -6:00 Chile EAS%sT 2015 Apr 26 3:00u
+ -5:00 - EAST
#
# Salas y Gómez Island is uninhabited.
# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
--- a/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Fri Feb 06 19:49:20 2015 +0300
+++ b/jdk/test/sun/util/calendar/zi/tzdata/zone.tab Mon Feb 09 09:52:48 2015 -0800
@@ -297,7 +297,7 @@
MV +0410+07330 Indian/Maldives
MW -1547+03500 Africa/Blantyre
MX +1924-09909 America/Mexico_City Central Time - most locations
-MX +2105-08646 America/Cancun Central Time - Quintana Roo
+MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo
MX +2058-08937 America/Merida Central Time - Campeche, Yucatan
MX +2540-10019 America/Monterrey Mexican Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas away from US border
MX +2550-09730 America/Matamoros US Central Time - Coahuila, Durango, Nuevo Leon, Tamaulipas near US border
--- a/langtools/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -290,3 +290,5 @@
73bbdcf236b297a0c1b8875f2eeba65eaf7ade60 jdk9-b45
e272d9be5f90edb6bb6b40f7816ec85eec0f5dc2 jdk9-b46
230c139552501e612dd0d4423ac30f94c1201c0d jdk9-b47
+5b102fc29edf8b7eee7df208d8a8bba0e0a52f3a jdk9-b48
+15c79f28e30a1be561abe0d67674232ad5034d32 jdk9-b49
--- a/langtools/make/tools/propertiesparser/gen/ClassGenerator.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/make/tools/propertiesparser/gen/ClassGenerator.java Mon Feb 09 09:52:48 2015 -0800
@@ -192,8 +192,8 @@
*/
String packageName(File file) {
String path = file.getAbsolutePath();
- int begin = path.indexOf("com" + File.separatorChar);
- String packagePath = path.substring(begin, path.lastIndexOf(File.separatorChar));
+ int begin = path.lastIndexOf(File.separatorChar + "com" + File.separatorChar);
+ String packagePath = path.substring(begin + 1, path.lastIndexOf(File.separatorChar));
String packageName = packagePath.replace(File.separatorChar, '.');
return packageName;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1931,6 +1931,11 @@
* Return the (most specific) base type of t that starts with the
* given symbol. If none exists, return null.
*
+ * Caveat Emptor: Since javac represents the class of all arrays with a singleton
+ * symbol Symtab.arrayClass, which by being a singleton cannot hold any discriminant,
+ * this method could yield surprising answers when invoked on arrays. For example when
+ * invoked with t being byte [] and sym being t.sym itself, asSuper would answer null.
+ *
* @param t a type
* @param sym a symbol
*/
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -720,7 +720,7 @@
public void visitParens(JCParens tree) {
tree.expr = translate(tree.expr, pt);
- tree.type = erasure(tree.type);
+ tree.type = erasure(tree.expr.type);
result = tree;
}
@@ -755,7 +755,7 @@
tree.clazz = translate(tree.clazz, null);
Type originalTarget = tree.type;
tree.type = erasure(tree.type);
- JCExpression newExpression = translate(tree.expr, erasure(tree.expr.type));
+ JCExpression newExpression = translate(tree.expr, tree.type);
if (newExpression != tree.expr) {
JCTypeCast typeCast = newExpression.hasTag(Tag.TYPECAST)
? (JCTypeCast) newExpression
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Mon Feb 09 09:52:48 2015 -0800
@@ -783,45 +783,4 @@
&& (n.endsWith(".jar") || n.endsWith(".zip"));
}
- /**
- * Utility method for converting a search path string to an array of directory and JAR file
- * URLs.
- *
- * Note that this method is called by the DocletInvoker.
- *
- * @param path the search path string
- * @return the resulting array of directory and JAR file URLs
- */
- public static URL[] pathToURLs(String path) {
- java.util.List<URL> urls = new ArrayList<>();
- for (String s: path.split(Pattern.quote(File.pathSeparator))) {
- if (!s.isEmpty()) {
- URL url = fileToURL(Paths.get(s));
- if (url != null) {
- urls.add(url);
- }
- }
- }
- return urls.toArray(new URL[urls.size()]);
- }
-
- /**
- * Returns the directory or JAR file URL corresponding to the specified local file name.
- *
- * @param file the Path object
- * @return the resulting directory or JAR file URL, or null if unknown
- */
- private static URL fileToURL(Path file) {
- Path p;
- try {
- p = file.toRealPath();
- } catch (IOException e) {
- p = file.toAbsolutePath();
- }
- try {
- return p.normalize().toUri().toURL();
- } catch (MalformedURLException e) {
- return null;
- }
- }
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java Mon Feb 09 09:52:48 2015 -0800
@@ -2145,7 +2145,8 @@
// For basic types, the coerce(...) in genExpr(...) will do
// the conversion.
if (!tree.clazz.type.isPrimitive() &&
- types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
+ !types.isSameType(tree.expr.type, tree.clazz.type) &&
+ types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties Mon Feb 09 09:52:48 2015 -0800
@@ -477,7 +477,7 @@
java.rmi.registry.*: compact2
java.rmi.server.*: compact2
java.security.*: compact1
-java.security.acl.*: compact3
+java.security.acl.*: compact1
java.security.cert.*: compact1
java.security.interfaces.*: compact1
java.security.spec.*: compact1
@@ -687,7 +687,7 @@
sun.rmi.transport.*: proprietary compact2
sun.rmi.transport.proxy.*: proprietary compact2
sun.rmi.transport.tcp.*: proprietary compact2
-sun.security.acl.*: proprietary compact3
+sun.security.acl.*: proprietary compact1
sun.security.action.*: proprietary compact1
sun.security.jca.*: proprietary compact1
sun.security.jgss.*: proprietary compact3
--- a/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/Analyzer.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/Analyzer.java Mon Feb 09 09:52:48 2015 -0800
@@ -218,7 +218,7 @@
Archive targetArchive = findArchive(t);
if (filter.accepts(o, archive, t, targetArchive)) {
addDep(o, t);
- if (!requires.contains(targetArchive)) {
+ if (archive != targetArchive && !requires.contains(targetArchive)) {
requires.add(targetArchive);
}
}
--- a/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/Archive.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/Archive.java Mon Feb 09 09:52:48 2015 -0800
@@ -75,20 +75,11 @@
}
public void addClass(Location origin) {
- Set<Location> set = deps.get(origin);
- if (set == null) {
- set = new HashSet<>();
- deps.put(origin, set);
- }
+ deps.computeIfAbsent(origin, _k -> new HashSet<>());
}
public void addClass(Location origin, Location target) {
- Set<Location> set = deps.get(origin);
- if (set == null) {
- set = new HashSet<>();
- deps.put(origin, set);
- }
- set.add(target);
+ deps.computeIfAbsent(origin, _k -> new HashSet<>()).add(target);
}
public Set<Location> getClasses() {
@@ -115,6 +106,10 @@
return filename;
}
+ public Path path() {
+ return path;
+ }
+
interface Visitor {
void visit(Location origin, Location target);
}
--- a/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.dev/share/classes/com/sun/tools/jdeps/JdepsTask.java Mon Feb 09 09:52:48 2015 -0800
@@ -611,6 +611,9 @@
deque.add(cn);
}
a.addClass(d.getOrigin(), d.getTarget());
+ } else {
+ // ensure that the parsed class is added the archive
+ a.addClass(d.getOrigin());
}
}
for (String name : a.reader().skippedEntries()) {
@@ -643,6 +646,7 @@
// if name is a fully-qualified class name specified
// from command-line, this class might already be parsed
doneClasses.add(classFileName);
+
for (Dependency d : finder.findDependencies(cf)) {
if (depth == 0) {
// ignore the dependency
@@ -654,6 +658,9 @@
if (!doneClasses.contains(cn) && !deque.contains(cn)) {
deque.add(cn);
}
+ } else {
+ // ensure that the parsed class is added the archive
+ a.addClass(d.getOrigin());
}
}
}
@@ -809,36 +816,53 @@
}
}
- private List<Archive> getClassPathArchives(String paths) throws IOException {
+ /*
+ * Returns the list of Archive specified in cpaths and not included
+ * initialArchives
+ */
+ private List<Archive> getClassPathArchives(String cpaths)
+ throws IOException
+ {
List<Archive> result = new ArrayList<>();
- if (paths.isEmpty()) {
+ if (cpaths.isEmpty()) {
return result;
}
- for (String p : paths.split(File.pathSeparator)) {
+ List<Path> paths = new ArrayList<>();
+ for (String p : cpaths.split(File.pathSeparator)) {
if (p.length() > 0) {
- List<Path> files = new ArrayList<>();
// wildcard to parse all JAR files e.g. -classpath dir/*
int i = p.lastIndexOf(".*");
if (i > 0) {
Path dir = Paths.get(p.substring(0, i));
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, "*.jar")) {
for (Path entry : stream) {
- files.add(entry);
+ paths.add(entry);
}
}
} else {
- files.add(Paths.get(p));
- }
- for (Path f : files) {
- if (Files.exists(f)) {
- result.add(Archive.getInstance(f));
- }
+ paths.add(Paths.get(p));
}
}
}
+ for (Path path : paths) {
+ boolean found = initialArchives.stream()
+ .map(Archive::path)
+ .anyMatch(p -> isSameFile(path, p));
+ if (!found && Files.exists(path)) {
+ result.add(Archive.getInstance(path));
+ }
+ }
return result;
}
+ private boolean isSameFile(Path p1, Path p2) {
+ try {
+ return Files.isSameFile(p1, p2);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
class RawOutputFormatter implements Analyzer.Visitor {
private final PrintWriter writer;
private String pkg = "";
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,19 +26,25 @@
package com.sun.tools.javadoc;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
import javax.tools.DocumentationTool;
import javax.tools.JavaFileManager;
import com.sun.javadoc.*;
-import com.sun.tools.javac.file.Locations;
import com.sun.tools.javac.util.ClientCodeException;
import com.sun.tools.javac.util.List;
+
import static com.sun.javadoc.LanguageVersion.*;
@@ -108,7 +114,7 @@
cpString = appendPath(System.getProperty("env.class.path"), cpString);
cpString = appendPath(System.getProperty("java.class.path"), cpString);
cpString = appendPath(docletPath, cpString);
- URL[] urls = Locations.pathToURLs(cpString);
+ URL[] urls = pathToURLs(cpString);
if (docletParentClassLoader == null)
appClassLoader = new URLClassLoader(urls, getDelegationClassLoader(docletClassName));
else
@@ -191,7 +197,7 @@
return false;
}
if (retVal instanceof Boolean) {
- return ((Boolean)retVal).booleanValue();
+ return ((Boolean)retVal);
} else {
messager.error(Messager.NOPOS, "main.must_return_boolean",
docletClassName, methodName);
@@ -215,7 +221,7 @@
return -1;
}
if (retVal instanceof Integer) {
- return ((Integer)retVal).intValue();
+ return ((Integer)retVal);
} else {
messager.error(Messager.NOPOS, "main.must_return_int",
docletClassName, methodName);
@@ -240,7 +246,7 @@
return false;
}
if (retVal instanceof Boolean) {
- return ((Boolean)retVal).booleanValue();
+ return ((Boolean)retVal);
} else {
messager.error(Messager.NOPOS, "main.must_return_boolean",
docletClassName, methodName);
@@ -326,11 +332,53 @@
} else {
messager.error(Messager.NOPOS, "main.exception_thrown",
docletClassName, methodName, exc.toString());
- exc.getTargetException().printStackTrace();
+ exc.getTargetException().printStackTrace(System.err);
}
throw new DocletInvokeException();
} finally {
Thread.currentThread().setContextClassLoader(savedCCL);
}
}
+
+ /**
+ * Utility method for converting a search path string to an array of directory and JAR file
+ * URLs.
+ *
+ * Note that this method is called by the DocletInvoker.
+ *
+ * @param path the search path string
+ * @return the resulting array of directory and JAR file URLs
+ */
+ private static URL[] pathToURLs(String path) {
+ java.util.List<URL> urls = new ArrayList<>();
+ for (String s: path.split(Pattern.quote(File.pathSeparator))) {
+ if (!s.isEmpty()) {
+ URL url = fileToURL(Paths.get(s));
+ if (url != null) {
+ urls.add(url);
+ }
+ }
+ }
+ return urls.toArray(new URL[urls.size()]);
+ }
+
+ /**
+ * Returns the directory or JAR file URL corresponding to the specified local file name.
+ *
+ * @param file the Path object
+ * @return the resulting directory or JAR file URL, or null if unknown
+ */
+ private static URL fileToURL(Path file) {
+ Path p;
+ try {
+ p = file.toRealPath();
+ } catch (IOException e) {
+ p = file.toAbsolutePath();
+ }
+ try {
+ return p.normalize().toUri().toURL();
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/CheckNoClassCastException.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8069265
+ * @summary ClassCastException when compiled with JDK 9b08+, JDK8 compiles OK.
+ * @run main CheckNoClassCastException
+ */
+import java.util.*;
+
+public class CheckNoClassCastException {
+ static String result = "";
+ public static void main(String[] args) {
+ ListFail.main(null);
+ MapFail.main(null);
+ if (!result.equals("ListFailDoneMapFailDone"))
+ throw new AssertionError("Incorrect result");
+ }
+}
+
+class ListFail {
+ static interface Foo {
+ }
+
+ public static void main(String[] args) {
+ List<Date> list = new ArrayList<>();
+ list.add(new Date());
+
+ List<Foo> cList = (List<Foo>) (List<?>) list;
+ Date date = (Date) cList.get(0);
+ CheckNoClassCastException.result += "ListFailDone";
+ }
+}
+
+
+class MapFail {
+ static interface Foo {
+ }
+
+ public static void main(String[] args) {
+ Map<String,Date> aMap = new HashMap<>();
+ aMap.put("test",new Date());
+
+ Map<String,Foo> m = (Map<String,Foo>) (Map<?,?>) aMap;
+ Date q = (Date) m.get("test");
+ CheckNoClassCastException.result += "MapFailDone";
+ }
+}
--- a/langtools/test/tools/javac/T7053059/DoubleCastTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/T7053059/DoubleCastTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -47,6 +47,7 @@
m1((byte[])m());
m1((byte[])os[0]);
m1((byte[])this.x);
+ m1((byte[])((byte []) (o = null)));
}
}
--- a/langtools/test/tools/javac/annotations/6359949/T6359949a.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/annotations/6359949/T6359949a.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,31 +1,8 @@
/*
- * Copyright (c) 2006, 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.
- */
-
-/**
- * @test
+ * @test /nodynamiccopyright/
* @bug 6359949
* @summary (at)Override of static shouldn't be accepted (compiler shouldissue an error/warning)
- * @compile/fail T6359949a.java
+ * @compile/fail/ref=T6359949a.out -XDrawDiagnostics T6359949a.java
*/
class Example {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/6359949/T6359949a.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+T6359949a.java:15:5: compiler.err.method.does.not.override.superclass
+1 error
--- a/langtools/test/tools/javac/annotations/default/A.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/annotations/default/A.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,37 +1,12 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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
+ * @test /nodynamiccopyright/
* @bug 4901262
* @summary Constraints regarding annotation defaults
* @author gafter
*
- * @compile A.java
- * @compile B.java
- * @compile C.java
- * @compile/fail Derr.java
- * @compile/fail Eerr.java
+ * @compile A.java B.java C.java
+ * @compile/fail/ref=Derr.out -XDrawDiagnostics Derr.java
+ * @compile/fail/ref=Eerr.out -XDrawDiagnostics Eerr.java
*/
public @interface A {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/default/Derr.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+Derr.java:24:1: compiler.err.annotation.missing.default.value: A, x
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/default/Eerr.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+Eerr.java:24:9: compiler.err.duplicate.annotation.member.value: x, A
+1 error
--- a/langtools/test/tools/javac/annotations/neg/Dep.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/annotations/neg/Dep.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,34 +1,10 @@
/*
- * 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
- * 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
+ * @test /nodynamiccopyright/
* @bug 4903501
* @summary Please add annotation <at>Deprecated to supplant the javadoc tag
* @author gafter
*
- * @compile/fail -Xlint:dep-ann -Werror Dep.java
- * @compile -Xlint:dep-ann Dep.java
+ * @compile/fail/ref=Dep.out -XDrawDiagnostics -Xlint:dep-ann -Werror Dep.java
*/
/** @deprecated */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/neg/Dep.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,4 @@
+Dep.java:11:1: compiler.warn.missing.deprecated.annotation
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/lambda/MethodReference55.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/lambda/MethodReference55.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,29 +1,6 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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 8004101
+ * @test /nodynamiccopyright/
+ * @bug 8004101 8072445
* @summary Add checks for method reference well-formedness
* @compile/fail/ref=MethodReference55.out -XDrawDiagnostics MethodReference55.java
*/
--- a/langtools/test/tools/javac/lambda/MethodReference55.out Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/lambda/MethodReference55.out Mon Feb 09 09:52:48 2015 -0800
@@ -1,3 +1,3 @@
-MethodReference55.java:36:11: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.bad.static.method.in.bound.lookup: kindname.method, m(java.lang.Object)))
-MethodReference55.java:39:9: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference55.V, @1384, kindname.class, MethodReference55<X>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.bad.static.method.in.bound.lookup: kindname.method, m(java.lang.Object))))
+MethodReference55.java:13:11: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.bad.static.method.in.bound.lookup: kindname.method, m(java.lang.Object)))
+MethodReference55.java:16:9: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference55.V, @361, kindname.class, MethodReference55<X>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.bad.static.method.in.bound.lookup: kindname.method, m(java.lang.Object))))
2 errors
--- a/langtools/test/tools/javac/lint/Deprecation.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/lint/Deprecation.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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
+ * @test /nodynamiccopyright/
* @bug 4821359
* @summary Add -Xlint flag
* @author gafter
*
- * @compile/fail -Xlint:deprecation -Werror Deprecation.java
+ * @compile/fail/ref=Deprecation.out -XDrawDiagnostics -Xlint:deprecation -Werror Deprecation.java
*/
/** @deprecated */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lint/Deprecation.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,4 @@
+Deprecation.java:14:17: compiler.warn.has.been.deprecated: A, compiler.misc.unnamed.package
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/lint/FallThrough.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/lint/FallThrough.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
+ * @test /nodynamiccopyright/
* @bug 4821359 4981267
* @summary Add -Xlint flag
* @author gafter
*
- * @compile/fail -Xlint:fallthrough -Werror FallThrough.java
+ * @compile/fail/ref=FallThrough.out -XDrawDiagnostics -Xlint:fallthrough -Werror FallThrough.java
*/
class FallThrough {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lint/FallThrough.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,4 @@
+FallThrough.java:16:9: compiler.warn.possible.fall-through.into.case
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/lint/Unchecked.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/lint/Unchecked.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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
+ * @test /nodynamiccopyright/
* @bug 4821359
* @summary Add -Xlint flag
* @author gafter
*
- * @compile/fail -Xlint:unchecked -Werror Unchecked.java
+ * @compile/fail/ref=Unchecked.out -XDrawDiagnostics -Xlint:unchecked -Werror Unchecked.java
*/
class Unchecked<T> {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/lint/Unchecked.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,4 @@
+Unchecked.java:12:32: compiler.warn.prob.found.req: (compiler.misc.unchecked.assign), Unchecked, Unchecked<java.lang.String>
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/staticImport/Ambig1.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/staticImport/Ambig1.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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
+ * @test /nodynamiccopyright/
* @bug 4929736
* @summary Missing ambiguity error when two methods are equally specific
* @author gafter
*
- * @compile/fail Ambig1.java
+ * @compile/fail/ref=Ambig1.out -XDrawDiagnostics Ambig1.java
*/
package ambig1;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/staticImport/Ambig1.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+Ambig1.java:24:9: compiler.err.ref.ambiguous: f, kindname.method, f(int), ambig1.B, kindname.method, f(int), ambig1.A
+1 error
--- a/langtools/test/tools/javac/staticImport/ImportPrivate.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/staticImport/ImportPrivate.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
+ * @test /nodynamiccopyright/
* @bug 4979456
* @summary NPE while compiling static import of inaccessible class member
* @author gafter
*
- * @compile/fail ImportPrivate.java
+ * @compile/fail/ref=ImportPrivate.out -XDrawDiagnostics ImportPrivate.java
*/
package importPrivate;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/staticImport/ImportPrivate.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,3 @@
+ImportPrivate.java:12:1: compiler.err.cant.resolve.location: kindname.static, m, , , kindname.class, importPrivate.A
+ImportPrivate.java:22:9: compiler.err.cant.resolve.location.args: kindname.method, m, , , (compiler.misc.location: kindname.class, importPrivate.MyTest, null)
+2 errors
--- a/langtools/test/tools/javac/staticImport/PrivateStaticImport.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/staticImport/PrivateStaticImport.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
+ * @test /nodynamiccopyright/
* @bug 4912075
* @summary static import of private field crashes compiler
* @author gafter
*
- * @compile/fail PrivateStaticImport.java
+ * @compile/fail/ref=PrivateStaticImport.out -XDrawDiagnostics PrivateStaticImport.java
*/
package psi;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/staticImport/PrivateStaticImport.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+PrivateStaticImport.java:18:17: compiler.err.cant.resolve.location: kindname.variable, FOO_VALUE, , , (compiler.misc.location: kindname.class, psi.Bar, null)
+1 error
--- a/langtools/test/tools/javac/staticImport/Shadow.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/staticImport/Shadow.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
+ * @test /nodynamiccopyright/
* @bug 5017254
* @summary compiler fails to shadow inapplicable method with static import
* @author gafter
*
- * @compile/fail Shadow.java
+ * @compile/fail/ref=Shadow.out -XDrawDiagnostics Shadow.java
*/
package shadow;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/staticImport/Shadow.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+Shadow.java:25:9: compiler.err.cant.apply.symbol: kindname.method, m1, int, compiler.misc.no.args, kindname.class, shadow.T2, (compiler.misc.arg.length.mismatch)
+1 error
--- a/langtools/test/tools/javac/staticImport/StaticImport2.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/javac/staticImport/StaticImport2.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,33 +1,10 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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
+ * @test /nodynamiccopyright/
* @bug 4855358
* @summary add support for JSR 201's static import facility
* @author gafter
*
- * @compile/fail StaticImport2.java
+ * @compile/fail/ref=StaticImport2.out -XDrawDiagnostics StaticImport2.java
*/
package p;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/staticImport/StaticImport2.out Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,2 @@
+StaticImport2.java:24:17: compiler.err.ref.ambiguous: K, kindname.variable, K, p.B, kindname.variable, K, p.A
+1 error
--- a/langtools/test/tools/jdeps/Basic.java Fri Feb 06 19:49:20 2015 +0300
+++ b/langtools/test/tools/jdeps/Basic.java Mon Feb 09 09:52:48 2015 -0800
@@ -23,9 +23,9 @@
/*
* @test
- * @bug 8003562 8005428 8015912 8027481 8048063
+ * @bug 8003562 8005428 8015912 8027481 8048063 8068937
* @summary Basic tests for jdeps tool
- * @build Test p.Foo p.Bar javax.activity.NotCompactProfile
+ * @build Test p.Foo p.Bar p.C p.SubClass q.Gee javax.activity.NotCompactProfile
* @run main Basic
*/
@@ -90,6 +90,18 @@
new String[] {"compact1"},
new String[] {"-verbose:package", "-e", "java\\.lang\\..*"});
+ // parse p.C, p.SubClass and q.*
+ // p.SubClass have no dependency other than p.C
+ // q.Gee depends on p.SubClass that should be found
+ test(testDir,
+ new String[] {"java.lang", "p"},
+ new String[] {"compact1", testDir.getName()},
+ new String[] {"-include", "p.C|p.SubClass|q\\..*"});
+ test(testDir,
+ new String[] {"java.lang", "p"},
+ new String[] {"compact1", testDir.getName()},
+ new String[] {"-classpath", testDir.getPath(), "-include", "p.C|p.SubClass|q\\..*"});
+
// test -classpath and -include options
test(null,
new String[] {"java.lang", "java.util", "java.lang.management",
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/p/C.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+public class C {
+ public String name() {
+ return "C";
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/p/SubClass.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package p;
+
+// SubClass only references types in package p
+public class SubClass extends C {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/q/Gee.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package q;
+
+public class Gee extends p.SubClass {
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/sjavac/ParallelCompilations.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary Test to check that -j option works with more than one value
+ * @bug 8071629
+ * @author sogoel
+ * @library /tools/lib
+ * @build Wrapper ToolBox
+ * @run main Wrapper ParallelCompilations
+ */
+
+import java.io.*;
+import java.nio.file.*;
+import com.sun.tools.sjavac.Main;
+
+class ParallelCompilations extends SJavacTester {
+ public static void main(String[] args) throws Exception {
+ new ParallelCompilations().run();
+ }
+
+ public void run() throws Exception {
+ ToolBox tb = new ToolBox();
+ final String SERVER_ARG = "--server:"
+ + "portfile=testportfile,"
+ + "background=false";
+
+ // Generate 10 files
+ for (int i = 0; i < 10; i++) {
+ String fileName = "Test" + i;
+ String content = "package foo"+ i + ";\n" +
+ "public class "+ fileName + "{\n" +
+ " public static void main(String[] args) {}\n" +
+ "\n}";
+ Path srcDir = Paths.get("src");
+ tb.writeJavaFiles(srcDir,content);
+ }
+ //Method will throw an exception if compilation fails
+ compile("src", "-d", "classes", "-j", "10", SERVER_ARG, "--log=debug");
+ }
+}
--- a/make/Images.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/Images.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -111,14 +111,16 @@
# Use this file inside the image as target for make rule
JIMAGE_TARGET_FILE := bin/java$(EXE_SUFFIX)
-$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JDK_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+ $(call DependOnVariable, JDK_MODULES_LIST)
$(ECHO) Creating jdk jimage
$(RM) -r $(JDK_IMAGE_DIR) $(JDK_SORTED_MODULES)
$(JIMAGE_TOOL) --mods $(JDK_MODULES_LIST) --output $(JDK_IMAGE_DIR) \
$(MODULES_XML) > $(JDK_SORTED_MODULES)
$(TOUCH) $@
-$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+ $(call DependOnVariable, JRE_MODULES_LIST)
$(ECHO) Creating jre jimage
$(RM) -r $(JRE_IMAGE_DIR) $(JRE_SORTED_MODULES)
$(JIMAGE_TOOL) --mods $(JRE_MODULES_LIST) --output $(JRE_IMAGE_DIR) \
@@ -131,7 +133,8 @@
COMPACT_EXTRA_MODULES := jdk.localedata jdk.crypto.pkcs11 jdk.crypto.ec
-$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT1_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+ $(call DependOnVariable, JRE_COMPACT1_MODULES_LIST)
$(ECHO) Creating jre compact1 jimage
$(RM) -r $(JRE_COMPACT1_IMAGE_DIR) $(JRE_COMPACT1_SORTED_MODULES)
$(JIMAGE_TOOL) \
@@ -140,7 +143,8 @@
$(MODULES_XML) > $(JRE_COMPACT1_SORTED_MODULES)
$(TOUCH) $@
-$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT2_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+ $(call DependOnVariable, JRE_COMPACT2_MODULES_LIST)
$(ECHO) Creating jre compact2 jimage
$(RM) -r $(JRE_COMPACT2_IMAGE_DIR) $(JRE_COMPACT2_SORTED_MODULES)
$(JIMAGE_TOOL) \
@@ -149,7 +153,8 @@
$(MODULES_XML) > $(JRE_COMPACT2_SORTED_MODULES)
$(TOUCH) $@
-$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES)
+$(JRE_COMPACT3_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(DEPENDENCIES) \
+ $(call DependOnVariable, JRE_COMPACT3_MODULES_LIST)
$(ECHO) Creating jre compact3 jimage
$(RM) -r $(JRE_COMPACT3_IMAGE_DIR) $(JRE_COMPACT3_SORTED_MODULES)
$(JIMAGE_TOOL) \
@@ -368,45 +373,59 @@
# Common way to emit a line into the release or info file
define info-file-item # name value
- $(PRINTF) '%s="%s"\n' $1 $2 >> $@
+ $(PRINTF) '%s="%s"\n' $1 $2 >> $@
endef
# Param 1 - The file containing the MODULES list
define create-info-file
- $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
- $(MKDIR) -p $(@D)
- $(RM) $@
- $(call info-file-item, "JAVA_VERSION", "$(JDK_VERSION)")
- $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
- $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
- $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
- $(if $(JDK_ARCH_ABI_PROP_NAME), \
- $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
- $(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)")
- $(call info-file-item, "MODULES", "`$(CAT) $1`")
+ $(call info-file-item, "JAVA_VERSION", "$(JDK_VERSION)")
+ $(call info-file-item, "OS_NAME", "$(REQUIRED_OS_NAME)")
+ $(call info-file-item, "OS_VERSION", "$(REQUIRED_OS_VERSION)")
+ $(call info-file-item, "OS_ARCH", "$(OPENJDK_TARGET_CPU_LEGACY)")
+ $(if $(JDK_ARCH_ABI_PROP_NAME), \
+ $(call info-file-item, "SUN_ARCH_ABI", "$(JDK_ARCH_ABI_PROP_NAME)"))
+ $(call info-file-item, "SOURCE", "$(ALL_SOURCE_TIPS)")
+ $(call info-file-item, "MODULES", "`$(CAT) $1`")
endef
+# Param 1 - The file containing the MODULES list
+define prepare-info-file
+ $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
+ $(MKDIR) -p $(@D)
+ $(RM) $@
+endef
+
+define info-file
+ $(call prepare-info-file, $1)
+ $(call create-info-file, $1)
+endef
+
+# Create a variable dependency file common for all release info files. The
+# sorted module list will only change if the image is regenerated, which will
+# trigger a rebuild of these files anyway.
+INFO_FILE_VARDEPS := $(call DependOnVariable, create-info-file)
+
ALL_SOURCE_TIPS = $(shell \
if [ -f $(SUPPORT_OUTPUTDIR)/source_tips ] ; then \
$(CAT) $(SUPPORT_OUTPUTDIR)/source_tips ; \
fi)
-$(JRE_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
- $(call create-info-file, $(JRE_SORTED_MODULES))
+$(JRE_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+ $(call info-file, $(JRE_SORTED_MODULES))
-$(JDK_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
- $(call create-info-file, $(JDK_SORTED_MODULES))
+$(JDK_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+ $(call info-file, $(JDK_SORTED_MODULES))
-$(JRE_COMPACT1_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
- $(call create-info-file, $(JRE_COMPACT1_SORTED_MODULES))
+$(JRE_COMPACT1_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+ $(call info-file, $(JRE_COMPACT1_SORTED_MODULES))
$(call info-file-item, "JAVA_PROFILE", "compact1")
-$(JRE_COMPACT2_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
- $(call create-info-file, $(JRE_COMPACT2_SORTED_MODULES))
+$(JRE_COMPACT2_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+ $(call info-file, $(JRE_COMPACT2_SORTED_MODULES))
$(call info-file-item, "JAVA_PROFILE", "compact2")
-$(JRE_COMPACT3_INFO_FILE): $(OUTPUT_ROOT)/spec.gmk $(SUPPORT_OUTPUTDIR)/source_tips
- $(call create-info-file, $(JRE_COMPACT3_SORTED_MODULES))
+$(JRE_COMPACT3_INFO_FILE): $(INFO_FILE_VARDEPS) $(SUPPORT_OUTPUTDIR)/source_tips
+ $(call info-file, $(JRE_COMPACT3_SORTED_MODULES))
$(call info-file-item, "JAVA_PROFILE", "compact3")
JRE_TARGETS += $(JRE_INFO_FILE)
--- a/make/Main.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/Main.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -402,6 +402,8 @@
verify-modules: exploded-image
+ test-make: clean-test-make
+
endif
################################################################################
@@ -446,7 +448,7 @@
# alias for ease of use.
jdk: exploded-image
-images: test-image jimages demos samples zip-security
+images: test-image jimages demos samples zip-security verify-modules
ifeq ($(OPENJDK_TARGET_OS), macosx)
images: mac-bundles
@@ -477,7 +479,7 @@
# file.
CLEAN_DIRS += hotspot jdk bootcycle-build test buildtools support \
- images make-support
+ images make-support test-make
CLEAN_DIR_TARGETS := $(addprefix clean-, $(CLEAN_DIRS))
CLEAN_PHASES := gensrc java native include
CLEAN_PHASE_TARGETS := $(addprefix clean-, $(CLEAN_PHASES))
--- a/make/ZipSource.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/ZipSource.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -71,7 +71,7 @@
$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjli/java_md*)))
# This dir needs to exist before macro is evaluated to avoid warning from find.
-$(eval $(call MakeDir, $(SUPPORT_OUTPUTDIR)/src))
+$(call MakeDir, $(SUPPORT_OUTPUTDIR)/src)
$(eval $(call SetupZipArchive,BUILD_SRC_ZIP, \
SRC := $(SRC_ZIP_SRCS) $(SUPPORT_OUTPUTDIR)/src, \
INCLUDES := $(SRC_ZIP_INCLUDES) launcher, \
--- a/make/common/IdlCompilation.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/common/IdlCompilation.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -99,7 +99,7 @@
$(if $(16),$(error Internal makefile error: Too many arguments to SetupIdlCompilation, please update IdlCompilation.gmk))
# Find all existing java files and existing class files.
- $$(eval $$(call MakeDir,$$($1_BIN)))
+ $$(call MakeDir,$$($1_BIN))
$1_SRCS := $$(shell find $$($1_SRC) -name "*.idl")
$1_BINS := $$(shell find $$($1_BIN) -name "*.java")
# Prepend the source/bin path to the filter expressions.
--- a/make/common/JavaCompilation.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/common/JavaCompilation.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -126,17 +126,20 @@
$1_FIND_PATTERNS:=$(FALSE_FIND_PATTERN) $$(patsubst %,$(SPACE)-o$(SPACE)-name$(SPACE)$(DQUOTE)*%$(DQUOTE),$$($1_SUFFIXES))
# On windows, a lot of includes/excludes risk making the command line too long, so
# writing the grep patterns to files.
+ # Grep returns 1 if nothing is matched. Do not fail the build for this.
ifneq (,$$($1_INCLUDES))
$1_GREP_INCLUDE_PATTERNS:=$$(call EscapeDollar, \
$$(foreach src,$$($1_SRCS), $$(addprefix $$(src)/,$$($1_INCLUDES))))
# If there are a lot of include patterns, output to file to shorten command lines
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
- $1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
+ $1_GREP_INCLUDES:=| ( $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS)) \
+ || test "$$$$?" = "1" )
else
$1_GREP_INCLUDE_OUTPUT:=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include $$(NEWLINE) \
$$(call ListPathsSafely,$1_GREP_INCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_include)
- $1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
+ $1_GREP_INCLUDES:=| ( $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include \
+ || test "$$$$?" = "1" )
endif
endif
ifneq (,$$($1_EXCLUDES)$$($1_EXCLUDE_FILES))
@@ -145,12 +148,14 @@
$$($1_EXCLUDES) $$($1_EXCLUDE_FILES))))
# If there are a lot of include patterns, output to file to shorten command lines
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
- $1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
+ $1_GREP_EXCLUDES:=| ( $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS)) \
+ || test "$$$$?" = "1" )
else
$1_GREP_EXCLUDE_OUTPUT=$(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude $$(NEWLINE) \
$$(call ListPathsSafely,$1_GREP_EXCLUDE_PATTERNS,\n, \
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
- $1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
+ $1_GREP_EXCLUDES:=| ( $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude \
+ || test "$$$$?" = "1" )
endif
endif
@@ -222,9 +227,11 @@
$$($1_CAPTURE_EXTRA_FILES)
# The capture metainf macro finds all files below the META-INF directory that are newer than the jar-file.
+ # Find returns non zero if the META-INF dir does not exist, ignore this.
ifeq (,$$($1_SKIP_METAINF))
$1_CAPTURE_METAINF =$$(foreach src,$$($1_SRCS), \
- ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+ ( ( $(FIND) $$(src)/META-INF -type f -a -newer $$@ 2> /dev/null || true ) \
+ | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents ) $$(NEWLINE) )
endif
# The capture deletes macro finds all deleted files and concatenates them. The resulting file
@@ -248,9 +255,11 @@
>> $$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)) \
$$($1_CAPTURE_EXTRA_FILES)
+ # Find returns non zero if the META-INF dir does not exist, ignore this.
ifeq (,$$($1_SKIP_METAINF))
$1_SCAPTURE_METAINF=$$(foreach src,$$($1_SRCS), \
- ( $(FIND) $$(src)/META-INF -type f 2> /dev/null | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
+ ( ( $(FIND) $$(src)/META-INF -type f 2> /dev/null || true ) \
+ | $(SED) 's|$$(src)/|-C $$(src) |g' >> \
$$($1_BIN)/_the.$$($1_JARNAME)_contents) $$(NEWLINE) )
endif
$1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
@@ -270,19 +279,37 @@
$1_JAR_UPDATE_OPTIONS := uf
endif
+ # Include all variables of significance in the vardeps file
+ $1_VARDEPS := $(JAR) $$($1_JAR_CREATE_OPTIONS) $$($1_MANIFEST) $(RELEASE) $(COMPANY_NAME) \
+ $$($1_JARMAIN) $$($1_EXTRA_MANIFEST_ATTR)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$(dir $$($1_JAR))_the.$$($1_JARNAME).vardeps)
+
# Here is the rule that creates/updates the jar file.
- $$($1_JAR) : $$($1_DEPS)
+ $$($1_JAR) : $$($1_DEPS) $$($1_MANIFEST) $$($1_VARDEPS_FILE)
$(MKDIR) -p $$($1_BIN)
$$($1_GREP_INCLUDE_OUTPUT)
$$($1_GREP_EXCLUDE_OUTPUT)
- $$(if $$($1_MANIFEST), \
- $(SED) -e "s#@@RELEASE@@#$(RELEASE)#" \
- -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $$($1_MANIFEST) > $$($1_MANIFEST_FILE) \
+ # If the vardeps file is part of the newer prereq list, it means that
+ # either the jar file does not exist, or we need to recreate it from
+ # from scratch anyway since a simple update will not catch all the
+ # potential changes.
+ $$(if $$(filter $$($1_VARDEPS_FILE) $$($1_MANIFEST), $$?), \
+ $$(if $$($1_MANIFEST), \
+ $(SED) -e "s#@@RELEASE@@#$(RELEASE)#" \
+ -e "s#@@COMPANY_NAME@@#$(COMPANY_NAME)#" $$($1_MANIFEST) > $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ , \
+ $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $$(if $$($1_JARMAIN), \
+ $(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $$(if $$($1_EXTRA_MANIFEST_ATTR), \
+ $(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE) $$(NEWLINE)) \
+ $(ECHO) Creating $$($1_NAME) $$(NEWLINE) \
+ $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
+ $$($1_SCAPTURE_CONTENTS) \
+ $$($1_SCAPTURE_METAINF) \
+ $$($1_SUPDATE_CONTENTS) \
+ $$($1_JARINDEX) && true \
, \
- $(RM) $$($1_MANIFEST_FILE) && $(TOUCH) $$($1_MANIFEST_FILE))
- $$(if $$($1_JARMAIN),$(ECHO) "Main-Class: $$(strip $$($1_JARMAIN))" >> $$($1_MANIFEST_FILE))
- $$(if $$($1_EXTRA_MANIFEST_ATTR),$(PRINTF) "$$($1_EXTRA_MANIFEST_ATTR)\n" >> $$($1_MANIFEST_FILE))
- $$(if $$(wildcard $$@), \
$(ECHO) Modifying $$($1_NAME) $$(NEWLINE) \
$$($1_CAPTURE_CONTENTS) \
$$($1_CAPTURE_METAINF) \
@@ -294,12 +321,6 @@
$(ZIP) -q -d $$@ `$(CAT) $$($1_DELETESS_FILE)` ; \
fi $$(NEWLINE) \
$$($1_UPDATE_CONTENTS) true $$(NEWLINE) \
- $$($1_JARINDEX) && true \
- , \
- $(ECHO) Creating $$($1_NAME) && $(JAR) $$($1_JAR_CREATE_OPTIONS) $$@ $$($1_MANIFEST_FILE) $$(NEWLINE) \
- $$($1_SCAPTURE_CONTENTS) \
- $$($1_SCAPTURE_METAINF) \
- $$($1_SUPDATE_CONTENTS) \
$$($1_JARINDEX) && true )
# Add jar to target list
@@ -431,7 +452,7 @@
$1_SRC:=$$(call ADD_SRCS,$$($1_SRC))
# Make sure the dirs exist.
$$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupJavaCompilation $1 contains missing directory $$d)))
- $$(eval $$(call MakeDir,$$($1_BIN)))
+ $$(call MakeDir,$$($1_BIN))
# Add all source roots to the find cache since we are likely going to run find
# on these more than once. The cache will only be updated if necessary.
$$(eval $$(call FillCacheFind,$$($1_SRC)))
@@ -475,23 +496,23 @@
$1_ALL_COPIES += $$(filter $$(addprefix %,$$($1_COPY)),$$($1_ALL_SRCS))
# Copy these explicitly
$1_ALL_COPIES += $$($1_COPY_FILES)
- # Copy must also respect filters.
- ifneq (,$$($1_INCLUDES))
- $1_ALL_COPIES := $$(filter $$($1_SRC_INCLUDES),$$($1_ALL_COPIES))
- endif
- ifneq (,$$($1_EXCLUDES))
- $1_ALL_COPIES := $$(filter-out $$($1_SRC_EXCLUDES),$$($1_ALL_COPIES))
- endif
- ifneq (,$$($1_EXCLUDE_FILES))
- $1_ALL_COPIES := $$(filter-out $$($1_EXCLUDE_FILES_PATTERN),$$($1_ALL_COPIES))
- endif
+ endif
+ # Copy must also respect filters.
+ ifneq (,$$($1_INCLUDES))
+ $1_ALL_COPIES := $$(filter $$($1_SRC_INCLUDES),$$($1_ALL_COPIES))
+ endif
+ ifneq (,$$($1_EXCLUDES))
+ $1_ALL_COPIES := $$(filter-out $$($1_SRC_EXCLUDES),$$($1_ALL_COPIES))
endif
- ifneq (,$$($1_ALL_COPIES))
- # Yep, there are files to be copied!
- $1_ALL_COPY_TARGETS:=
- $$(foreach i,$$($1_ALL_COPIES),$$(eval $$(call add_file_to_copy,$1,$$i)))
- # Now we can depend on $$($1_ALL_COPY_TARGETS) to copy all files!
- endif
+ ifneq (,$$($1_EXCLUDE_FILES))
+ $1_ALL_COPIES := $$(filter-out $$($1_EXCLUDE_FILES_PATTERN),$$($1_ALL_COPIES))
+ endif
+ ifneq (,$$($1_ALL_COPIES))
+ # Yep, there are files to be copied!
+ $1_ALL_COPY_TARGETS:=
+ $$(foreach i,$$($1_ALL_COPIES),$$(eval $$(call add_file_to_copy,$1,$$i)))
+ # Now we can depend on $$($1_ALL_COPY_TARGETS) to copy all files!
+ endif
# Find all property files to be copied and cleaned from source to bin.
ifneq (,$$($1_CLEAN)$$($1_CLEAN_FILES))
@@ -535,9 +556,14 @@
$1_SJAVAC:=$$(subst com.sun.tools.javac.Main,com.sun.tools.sjavac.Main,$$($1_JAVAC))
# Set the $1_REMOTE to spawn a background javac server.
- $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
+ $1_REMOTE:=--server:portfile=$$($1_SJAVAC_PORTFILE),id=$1,sjavac=$$(subst \
+ $$(SPACE),%20,$$(subst $$(COMMA),%2C,$$(strip $$($1_SERVER_JVM) $$($1_SJAVAC))))
- $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS)
+ $1_VARDEPS := $$($1_JVM) $$($1_SJAVAC) $$($1_SJAVAC_ARGS) $$($1_FLAGS) \
+ $$($1_HEADERS_ARG) $$($1_BIN)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+
+ $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
$(MKDIR) -p $$(@D) $$(dir $$($1_SJAVAC_PORTFILE))
# As a workaround for sjavac not tracking api changed from the classpath, force full
# recompile if an external dependency, which is something other than a source
@@ -592,8 +618,11 @@
$1_HEADER_TARGETS := $$($1_HEADERS)/_the.$1_headers
endif
+ $1_VARDEPS := $$($1_JVM) $$($1_JAVAC) $$($1_FLAGS) $$($1_BIN) $$($1_HEADERS_ARG)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, $$($1_BIN)/_the.$1.vardeps)
+
# When not using sjavac, pass along all sources to javac using an @file.
- $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS)
+ $$($1_BIN)/_the.$1_batch: $$($1_SRCS) $$($1_DEPENDS) $$($1_VARDEPS_FILE)
$(MKDIR) -p $$(@D)
$(RM) $$($1_BIN)/_the.$1_batch $$($1_BIN)/_the.$1_batch.tmp
$$(call ListPathsSafely,$1_SRCS,\n, >> $$($1_BIN)/_the.$1_batch.tmp)
@@ -659,4 +688,5 @@
$(if $(findstring yes, $(ENABLE_SJAVAC)), $(strip $2)/_the.$(strip $1)_pubapi, \
$(strip $2)/_the.$(strip $1)_batch)
endef
-endif
+
+endif # _JAVA_COMPILATION_GMK
--- a/make/common/MakeBase.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/common/MakeBase.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -349,7 +349,7 @@
# (and causing a crash on Cygwin).
# Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris.
# Only use time if it's GNU time which supports format and output file.
- WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(BASH)
+ WRAPPER_SHELL:=$$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(SHELL)
SHELL=$$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL)
endif
# Never remove warning messages; this is just for completeness
@@ -392,11 +392,9 @@
endef
# Make directory without forking mkdir if not needed
-define MakeDir
- ifneq ($$(wildcard $1 $2 $3 $4 $5 $6 $7 $8 $9),$$(strip $1 $2 $3 $4 $5 $6 $7 $8 $9))
- $$(shell $(MKDIR) -p $1 $2 $3 $4 $5 $6 $7 $8 $9)
- endif
-endef
+MakeDir = \
+ $(strip $(if $(subst $(wildcard $1 $2 $3 $4 $5 $6 $7 $8 $9),,$(strip $1 $2 $3 $4 $5 $6 $7 $8 $9)),\
+ $(shell $(MKDIR) -p $1 $2 $3 $4 $5 $6 $7 $8 $9)))
ifeq ($(OPENJDK_TARGET_OS),solaris)
# On Solaris, if the target is a symlink and exists, cp won't overwrite.
@@ -446,6 +444,11 @@
# Filter out duplicate sub strings while preserving order. Keeps the first occurance.
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
+# String equals
+equals = \
+ $(and $(findstring $(strip $1),$(strip $2)),\
+ $(findstring $(strip $2),$(strip $1)))
+
ifneq ($(DISABLE_CACHE_FIND), true)
################################################################################
# In Cygwin, finds are very costly, both because of expensive forks and because
@@ -543,6 +546,80 @@
endef
################################################################################
+# ShellQuote
+#
+# Quotes a string with single quotes and replaces single quotes with '\'' so
+# that the contents survives being given to the shell.
+
+ShellQuote = \
+ $(SQUOTE)$(subst $(SQUOTE),$(SQUOTE)\$(SQUOTE)$(SQUOTE),$(strip $1))$(SQUOTE)
+
+################################################################################
+# Write to and read from file
+
+# Param 1 - File to read
+ReadFile = \
+ $(shell $(CAT) $1)
+
+# Param 1 - Text to write
+# Param 2 - File to write to
+# Use printf to get consistent behavior on all platforms.
+WriteFile = \
+ $(shell $(PRINTF) "%s" $(call ShellQuote, $1) > $2)
+
+################################################################################
+# DependOnVariable
+#
+# This macro takes a variable name and puts the value in a file only if the
+# value has changed since last. The name of the file is returned. This can be
+# used to create rule dependencies on make variable values. The following
+# example would get rebuilt if the value of SOME_VAR was changed:
+#
+# path/to/some-file: $(call DependOnVariable, SOME_VAR)
+# echo $(SOME_VAR) > $@
+#
+# Note that leading and trailing white space in the value is ignored.
+#
+
+# Defines the sub directory structure to store variable value file in
+DependOnVariableDirName = \
+ $(strip $(subst $(SRC_ROOT)/,,\
+ $(if $(filter /%, $(firstword $(MAKEFILE_LIST))), \
+ $(firstword $(MAKEFILE_LIST)), \
+ $(CURDIR)/$(firstword $(MAKEFILE_LIST)))))
+
+# Defines the name of the file to store variable value in. Generates a name
+# unless parameter 2 is given.
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariableFileName = \
+ $(strip $(if $(strip $2), $2, \
+ $(MAKESUPPORT_OUTPUTDIR)/vardeps/$(DependOnVariableDirName)/$(strip $1).vardeps))
+
+# Does the actual work with parameters stripped.
+# If the file exists AND the contents is the same as the variable, do nothing
+# else print a new file.
+# Always returns the name of the file where the value was printed.
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariableHelper = \
+ $(strip $(if $(and $(wildcard $(call DependOnVariableFileName, $1, $2)),\
+ $(call equals, $(strip $($1)), \
+ $(call ReadFile, $(call DependOnVariableFileName, $1, $2)))),,\
+ $(call MakeDir, $(dir $(call DependOnVariableFileName, $1, $2))) \
+ $(if $(findstring $(LOG_LEVEL), trace), \
+ $(info Variable $1: >$(strip $($1))<) \
+ $(info File: >$(call ReadFile, $(call DependOnVariableFileName, $1, $2))<)) \
+ $(call WriteFile, $($1), $(call DependOnVariableFileName, $1, $2))) \
+ $(call DependOnVariableFileName, $1, $2))
+
+# Main macro
+# Param 1 - Name of variable
+# Param 2 - (optional) name of file to store value in
+DependOnVariable = \
+ $(call DependOnVariableHelper,$(strip $1),$(strip $2))
+
+################################################################################
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, , common/MakeBase.gmk))
--- a/make/common/NativeCompilation.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/common/NativeCompilation.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -114,7 +114,7 @@
endif
endif
- $$($1_$2_OBJ) : $2 | $$($1_BUILD_INFO)
+ $$($1_$2_OBJ) : $2 $$($1_COMPILE_VARDEPS_FILE) | $$($1_BUILD_INFO)
$(ECHO) $(LOG_INFO) "Compiling $$(notdir $2) (for $$(notdir $$($1_TARGET)))"
ifneq ($(TOOLCHAIN_TYPE), microsoft)
# The Solaris studio compiler doesn't output the full path to the object file in the
@@ -133,7 +133,8 @@
($$($1_$2_COMP) $$($1_$2_FLAGS) -showIncludes $$($1_$2_DEBUG_OUT_FLAGS) \
$(CC_OUT_OPTION)$$($1_$2_OBJ) $2 ; echo $$$$? > $$($1_$2_DEP).exitvalue) \
| $(TEE) $$($1_$2_DEP).raw | $(GREP) -v -e "^Note: including file:" \
- -e "^$(notdir $2)$$$$" ; exit `cat $$($1_$2_DEP).exitvalue`
+ -e "^$(notdir $2)$$$$" || test "$$$$?" = "1" ; \
+ exit `cat $$($1_$2_DEP).exitvalue`
$(RM) $$($1_$2_DEP).exitvalue
($(ECHO) $$@: \\ \
&& $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_$2_DEP).raw) > $$($1_$2_DEP)
@@ -306,7 +307,7 @@
endif
# Make sure the dirs exist.
- $$(eval $$(call MakeDir,$$($1_OBJECT_DIR) $$($1_OUTPUT_DIR)))
+ $$(call MakeDir,$$($1_OBJECT_DIR) $$($1_OUTPUT_DIR))
$$(foreach d,$$($1_SRC), $$(if $$(wildcard $$d),,$$(error SRC specified to SetupNativeCompilation $1 contains missing directory $$d)))
# Find all files in the source trees. Sort to remove duplicates.
@@ -426,15 +427,16 @@
$1_BUILD_INFO := $$($1_OBJECT_DIR)/_build-info.marker
- # Setup rule for printing progress info when compiling source files.
- # This is a rough heuristic and may not always print accurate information.
- $$($1_BUILD_INFO): $$($1_SRCS)
- ifeq ($$(wildcard $$($1_TARGET)),)
- $(ECHO) 'Creating $$($1_BASENAME) from $$(words $$?) file(s)'
- else
- $(ECHO) 'Updating $$($1_BASENAME) from $$(words $$?) file(s)'
- endif
- $(TOUCH) $$@
+ # Track variable changes for all variables that affect the compilation command
+ # lines for all object files in this setup. This includes at least all the
+ # variables used in the call to add_native_source below.
+ $1_COMPILE_VARDEPS := $$($1_CFLAGS) $$($1_EXTRA_CFLAGS) $(SYSROOT_CFLAGS) \
+ $$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) \
+ $$($1_CC) $$($1_CXX) $$($1_OBJC) $$($1_ASFLAGS) \
+ $$(foreach s, $$($1_SRCS), \
+ $$($1_$$(notdir $$s)_CFLAGS) $$($1_$$(notdir $$s)_CXXFLAGS))
+ $1_COMPILE_VARDEPS_FILE := $$(call DependOnVariable, $1_COMPILE_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).comp.vardeps)
# Now call add_native_source for each source file we are going to compile.
$$(foreach p,$$($1_SRCS), \
@@ -444,13 +446,28 @@
$$($1_CXXFLAGS) $$($1_EXTRA_CXXFLAGS) $(SYSROOT_CFLAGS), \
$$($1_CXX),$$($1_OBJC),$$($1_ASFLAGS))))
+ # Setup rule for printing progress info when compiling source files.
+ # This is a rough heuristic and may not always print accurate information.
+ $$($1_BUILD_INFO): $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
+ ifeq ($$(wildcard $$($1_TARGET)),)
+ $(ECHO) 'Creating $$($1_BASENAME) from $$(words $$(filter-out %.vardeps, $$?)) file(s)'
+ else
+ $(ECHO) 'Updating $$($1_BASENAME) from $$(words $$(filter-out %.vardeps, $$?)) file(s)'
+ endif
+ $(TOUCH) $$@
+
# On windows we need to create a resource file
ifeq ($(OPENJDK_TARGET_OS), windows)
ifneq (,$$($1_VERSIONINFO_RESOURCE))
$1_RES:=$$($1_OBJECT_DIR)/$$($1_BASENAME).res
$1_RES_DEP:=$$($1_RES).d
-include $$($1_RES_DEP)
- $$($1_RES): $$($1_VERSIONINFO_RESOURCE)
+
+ $1_RES_VARDEPS := $(RC) $$($1_RC_FLAGS)
+ $1_RES_VARDEPS_FILE := $$(call DependOnVariable, $1_RES_VARDEPS, \
+ $$($1_RES).vardeps)
+
+ $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))"
$(RC) $$($1_RC_FLAGS) $(CC_OUT_OPTION)$$@ $$($1_VERSIONINFO_RESOURCE)
# Windows RC compiler does not support -showIncludes, so we mis-use CL for this.
@@ -462,7 +479,9 @@
ifneq (,$$($1_MANIFEST))
$1_GEN_MANIFEST:=$$($1_OBJECT_DIR)/$$($1_PROGRAM).manifest
IMVERSIONVALUE:=$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION).$(JDK_UPDATE_VERSION).$(COOKED_BUILD_NUMBER)
- $$($1_GEN_MANIFEST): $$($1_MANIFEST)
+ $1_MANIFEST_VARDEPS_FILE := $$(call DependOnVariable, IMVERSIONVALUE, \
+ $$($1_GEN_MANIFEST).vardeps)
+ $$($1_GEN_MANIFEST): $$($1_MANIFEST) $$($1_MANIFEST_VARDEPS_FILE)
$(SED) 's%IMVERSION%$$(IMVERSIONVALUE)%g;s%PROGRAM%$$($1_PROGRAM)%g' $$< > $$@
endif
endif
@@ -575,8 +594,13 @@
$1_EXTRA_LDFLAGS_SUFFIX += $(GLOBAL_LDFLAGS_SUFFIX)
+ $1_VARDEPS := $$($1_LD) $(SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+ $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_REAL_MAPFILE) \
- $$($1_DEBUGINFO_EXTRA_DEPS)
+ $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking $$($1_BASENAME)"
$$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $(SYSROOT_LDFLAGS) \
$(LD_OUT_OPTION)$$@ \
@@ -592,8 +616,12 @@
endif
ifneq (,$$($1_STATIC_LIBRARY))
+ $1_VARDEPS := $(AR) $$($1_ARFLAGS) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
# Generating a static library, ie object file archive.
- $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES)
+ $$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Archiving $$($1_STATIC_LIBRARY)"
$(AR) $$($1_ARFLAGS) $(AR_OUT_OPTION)$$($1_TARGET) $$($1_EXPECTED_OBJS) \
$$($1_RES) $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
@@ -603,8 +631,13 @@
# A executable binary has been specified, setup the target for it.
$1_EXTRA_LDFLAGS_SUFFIX += $(GLOBAL_LDFLAGS_SUFFIX)
+ $1_VARDEPS := $$($1_LDEXE) $(SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \
+ $$($1_LDFLAGS_SUFFIX) $$($1_EXTRA_LDFLAGS_SUFFIX)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS, \
+ $$($1_OBJECT_DIR)/$$($1_NOSUFFIX).vardeps)
+
$$($1_TARGET): $$($1_EXPECTED_OBJS) $$($1_RES) $$($1_GEN_MANIFEST) \
- $$($1_DEBUGINFO_EXTRA_DEPS)
+ $$($1_DEBUGINFO_EXTRA_DEPS) $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Linking executable $$($1_BASENAME)"
$$($1_LDEXE) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $(SYSROOT_LDFLAGS) \
$(EXE_OUT_OPTION)$$($1_TARGET) \
--- a/make/common/TextFileProcessing.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/make/common/TextFileProcessing.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -34,7 +34,7 @@
# param 3 = the target base directory
# param 4 = the target file name (possibly with a partial path)
define SetupSingleTextFileForProcessing
- $(strip $3)/$(strip $4): $2
+ $(strip $3)/$(strip $4): $2 $$($1_VARDEPS_FILE)
$(ECHO) $(LOG_INFO) "Processing $(strip $4)"
$(MKDIR) -p '$$(@D)'
$(RM) '$$@' '$$@.includes.tmp' '$$@.replacements.tmp'
@@ -193,6 +193,9 @@
$1_INCLUDES_COMMAND_LINE := $(CAT)
endif
+ $1_VARDEPS := $$($1_INCLUDES_COMMAND_LINE) $$($1_REPLACEMENTS_COMMAND_LINE)
+ $1_VARDEPS_FILE := $$(call DependOnVariable, $1_VARDEPS)
+
# Reset target list before populating it
$1 :=
--- a/modules.xml Fri Feb 06 19:49:20 2015 +0300
+++ b/modules.xml Mon Feb 09 09:52:48 2015 -0800
@@ -108,6 +108,9 @@
<name>java.security</name>
</export>
<export>
+ <name>java.security.acl</name>
+ </export>
+ <export>
<name>java.security.cert</name>
</export>
<export>
@@ -446,7 +449,6 @@
<depend re-exports="true">java.management</depend>
<depend re-exports="true">java.naming</depend>
<depend re-exports="true">java.prefs</depend>
- <depend re-exports="true">java.security.acl</depend>
<depend re-exports="true">java.security.jgss</depend>
<depend re-exports="true">java.security.sasl</depend>
<depend re-exports="true">java.sql.rowset</depend>
@@ -891,13 +893,6 @@
<depend re-exports="true">java.xml.ws</depend>
</module>
<module>
- <name>java.security.acl</name>
- <depend>java.base</depend>
- <export>
- <name>java.security.acl</name>
- </export>
- </module>
- <module>
<name>java.security.jgss</name>
<depend>java.base</depend>
<depend>java.naming</depend>
--- a/nashorn/.hgtags Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/.hgtags Mon Feb 09 09:52:48 2015 -0800
@@ -281,3 +281,5 @@
3c2bbeda038aef7061455fec604db7d8a342fac5 jdk9-b45
2ecf0a617f0f9af1ffd278a0c70e76f1946ce773 jdk9-b46
29046d42a95e5b9f105ab086a628bbd7f81c915d jdk9-b47
+f08660f30051ba0b38ad00e692979b37d107c9c4 jdk9-b48
+2ae58b5f05f803a469f0f6c1ed72c6b5313f4ff0 jdk9-b49
--- a/nashorn/samples/javashell.js Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/samples/javashell.js Mon Feb 09 09:52:48 2015 -0800
@@ -40,6 +40,7 @@
var Arrays = Java.type("java.util.Arrays");
var BufferedReader = Java.type("java.io.BufferedReader");
var FileWriter = Java.type("java.io.FileWriter");
+var List = Java.type("java.util.List");
var LocalDateTime = Java.type("java.time.LocalDateTime");
var InputStreamReader = Java.type("java.io.InputStreamReader");
var PrintWriter = Java.type("java.io.PrintWriter");
@@ -121,7 +122,7 @@
// execute code command
function exec(args) {
// build child process and start it!
- new ProcessBuilder(Arrays.asList(args.split(' ')))
+ new ProcessBuilder(Java.to(args.split(' '), List))
.inheritIO()
.start()
.waitFor();
--- a/nashorn/samples/shell.js Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/samples/shell.js Mon Feb 09 09:52:48 2015 -0800
@@ -42,6 +42,7 @@
var Arrays = Java.type("java.util.Arrays");
var BufferedReader = Java.type("java.io.BufferedReader");
var InputStreamReader = Java.type("java.io.InputStreamReader");
+ var List = Java.type("java.util.List");
var ProcessBuilder = Java.type("java.lang.ProcessBuilder");
var System = Java.type("java.lang.System");
@@ -66,7 +67,7 @@
}
} else {
// build child process and start it!
- new ProcessBuilder(Arrays.asList(args))
+ new ProcessBuilder(Java.to(args, List))
.inheritIO()
.start()
.waitFor();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Mon Feb 09 09:52:48 2015 -0800
@@ -88,6 +88,7 @@
import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.util.List;
+import java.util.Objects;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.LinkRequest;
@@ -252,7 +253,7 @@
// Make sure we filter the invocation before linking it into the call site. This is typically used to match the
// return type of the invocation to the call site.
guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices);
- guardedInvocation.getClass(); // null pointer check
+ Objects.requireNonNull(guardedInvocation);
int newRelinkCount = relinkCount;
// Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java Mon Feb 09 09:52:48 2015 -0800
@@ -84,6 +84,7 @@
package jdk.internal.dynalink.beans;
import java.io.Serializable;
+import java.util.Objects;
/**
* Object that represents the static facet of a class (its static methods, properties, and fields, as well as
@@ -106,8 +107,7 @@
private final Class<?> clazz;
/*private*/ StaticClass(final Class<?> clazz) {
- clazz.getClass(); // NPE check
- this.clazz = clazz;
+ this.clazz = Objects.requireNonNull(clazz);
}
/**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Mon Feb 09 09:52:48 2015 -0800
@@ -91,6 +91,7 @@
import java.lang.invoke.SwitchPoint;
import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
+import java.util.Objects;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.Guards;
@@ -170,8 +171,7 @@
* @throws NullPointerException if invocation is null.
*/
public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class<? extends Throwable> exception) {
- invocation.getClass(); // NPE check
- this.invocation = invocation;
+ this.invocation = Objects.requireNonNull(invocation);
this.guard = guard;
this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
this.exception = exception;
@@ -190,8 +190,7 @@
* @throws NullPointerException if invocation is null.
*/
public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class<? extends Throwable> exception) {
- invocation.getClass(); // NPE check
- this.invocation = invocation;
+ this.invocation = Objects.requireNonNull(invocation);
this.guard = guard;
this.switchPoints = switchPoints == null ? null : switchPoints.clone();
this.exception = exception;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java Mon Feb 09 09:52:48 2015 -0800
@@ -91,6 +91,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import java.util.StringTokenizer;
import java.util.WeakHashMap;
import jdk.internal.dynalink.CallSiteDescriptor;
@@ -123,9 +124,9 @@
* in fact return a weakly-referenced canonical instance.
*/
public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) {
- name.getClass(); // NPE check
- methodType.getClass(); // NPE check
- lookup.getClass(); // NPE check
+ Objects.requireNonNull(name);
+ Objects.requireNonNull(methodType);
+ Objects.requireNonNull(lookup);
final String[] tokenizedName = tokenizeName(name);
if(isPublicLookup(lookup)) {
return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Feb 09 09:52:48 2015 -0800
@@ -39,6 +39,7 @@
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.Locale;
+import java.util.Objects;
import java.util.ResourceBundle;
import javax.script.AbstractScriptEngine;
import javax.script.Bindings;
@@ -360,7 +361,7 @@
}
private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
- name.getClass(); // null check
+ Objects.requireNonNull(name);
assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here";
Global invokeGlobal = null;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java Mon Feb 09 09:52:48 2015 -0800
@@ -28,6 +28,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory;
import jdk.nashorn.internal.runtime.Context;
@@ -177,7 +178,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
- classFilter.getClass(); // null check
+ Objects.requireNonNull(classFilter);
return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter);
}
@@ -192,7 +193,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String... args) {
- args.getClass(); // null check
+ Objects.requireNonNull(args);
return newEngine(args, getAppClassLoader(), null);
}
@@ -208,7 +209,7 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
- args.getClass(); // null check
+ Objects.requireNonNull(args);
return newEngine(args, appLoader, null);
}
@@ -225,8 +226,8 @@
* denies {@code RuntimePermission("nashorn.setConfig")}
*/
public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
- args.getClass(); // null check
- classFilter.getClass(); // null check
+ Objects.requireNonNull(args);
+ Objects.requireNonNull(classFilter);
return newEngine(args, appLoader, classFilter);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java Mon Feb 09 09:52:48 2015 -0800
@@ -39,6 +39,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.script.Bindings;
@@ -180,7 +181,7 @@
* @return return value of function
*/
public Object callMember(final String functionName, final Object... args) {
- functionName.getClass(); // null check
+ Objects.requireNonNull(functionName);
final Global oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
@@ -213,7 +214,7 @@
@Override
public Object getMember(final String name) {
- name.getClass();
+ Objects.requireNonNull(name);
return inGlobal(new Callable<Object>() {
@Override public Object call() {
return wrap(sobj.get(name), global);
@@ -232,7 +233,7 @@
@Override
public boolean hasMember(final String name) {
- name.getClass();
+ Objects.requireNonNull(name);
return inGlobal(new Callable<Boolean>() {
@Override public Boolean call() {
return sobj.has(name);
@@ -251,13 +252,13 @@
@Override
public void removeMember(final String name) {
- name.getClass();
+ Objects.requireNonNull(name);
remove(name);
}
@Override
public void setMember(final String name, final Object value) {
- name.getClass();
+ Objects.requireNonNull(name);
put(name, value);
}
@@ -425,9 +426,7 @@
@Override
public void putAll(final Map<? extends String, ? extends Object> map) {
- if (map == null) {
- throw new NullPointerException("map is null");
- }
+ Objects.requireNonNull(map, "map is null");
final ScriptObject oldGlobal = Context.getGlobal();
final boolean globalChanged = (oldGlobal != global);
inGlobal(new Callable<Object>() {
@@ -804,9 +803,9 @@
* @throws IllegalArgumentException if key is empty string
*/
private static void checkKey(final Object key) {
- if (key == null) {
- throw new NullPointerException("key can not be null");
- } else if (!(key instanceof String)) {
+ Objects.requireNonNull(key, "key can not be null");
+
+ if (!(key instanceof String)) {
throw new ClassCastException("key should be a String. It is " + key.getClass().getName() + " instead.");
} else if (((String)key).length() == 0) {
throw new IllegalArgumentException("key can not be empty");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/URLReader.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/URLReader.java Mon Feb 09 09:52:48 2015 -0800
@@ -30,6 +30,7 @@
import java.io.Reader;
import java.net.URL;
import java.nio.charset.Charset;
+import java.util.Objects;
import jdk.nashorn.internal.runtime.Source;
/**
@@ -77,8 +78,7 @@
* @throws NullPointerException if url is null
*/
public URLReader(final URL url, final Charset cs) {
- // null check
- url.getClass();
+ Objects.requireNonNull(url);
this.url = url;
this.cs = cs;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java Mon Feb 09 09:52:48 2015 -0800
@@ -926,9 +926,7 @@
@Override
public Node leaveTryNode(final TryNode tryNode) {
tryNode.setException(exceptionSymbol());
- if (tryNode.getFinallyBody() != null) {
- tryNode.setFinallyCatchAll(exceptionSymbol());
- }
+ assert tryNode.getFinallyBody() == null;
end(tryNode);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Feb 09 09:52:48 2015 -0800
@@ -85,7 +85,6 @@
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.BlockStatement;
import jdk.nashorn.internal.ir.BreakNode;
-import jdk.nashorn.internal.ir.BreakableNode;
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
@@ -102,6 +101,7 @@
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -1110,7 +1110,14 @@
@Override
public boolean enterBlock(final Block block) {
- method.label(block.getEntryLabel());
+ final Label entryLabel = block.getEntryLabel();
+ if (entryLabel.isBreakTarget()) {
+ // Entry label is a break target only for an inlined finally block.
+ assert !method.isReachable();
+ method.breakLabel(entryLabel, lc.getUsedSlotCount());
+ } else {
+ method.label(entryLabel);
+ }
if(!method.isReachable()) {
return false;
}
@@ -1240,6 +1247,11 @@
return enterJumpStatement(breakNode);
}
+ @Override
+ public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ return enterJumpStatement(jumpToInlinedFinally);
+ }
+
private boolean enterJumpStatement(final JumpStatement jump) {
if(!method.isReachable()) {
return false;
@@ -1247,9 +1259,8 @@
enterStatement(jump);
method.beforeJoinPoint(jump);
- final BreakableNode target = jump.getTarget(lc);
- popScopesUntil(target);
- final Label targetLabel = jump.getTargetLabel(target);
+ popScopesUntil(jump.getPopScopeLimit(lc));
+ final Label targetLabel = jump.getTargetLabel(lc);
targetLabel.markAsBreakTarget();
method._goto(targetLabel);
@@ -3053,6 +3064,14 @@
if (method.isReachable()) {
method._goto(skip);
}
+
+ for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+ TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
+ // All inlined finallies end with a jump or a return
+ assert !method.isReachable();
+ }
+
+
method._catch(recovery);
method.store(vmException, EXCEPTION_TYPE);
@@ -3112,15 +3131,14 @@
catchBody.accept(this);
leaveBlock(catchBlock);
lc.pop(catchBlock);
- if(method.isReachable()) {
- method._goto(afterCatch);
- }
if(nextCatch != null) {
+ if(method.isReachable()) {
+ method._goto(afterCatch);
+ }
method.breakLabel(nextCatch, lc.getUsedSlotCount());
}
}
- assert !method.isReachable();
// afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
method.label(afterCatch);
if(method.isReachable()) {
@@ -3129,6 +3147,8 @@
method.label(skip);
// Finally body is always inlined elsewhere so it doesn't need to be emitted
+ assert tryNode.getFinallyBody() == null;
+
return false;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java Mon Feb 09 09:52:48 2015 -0800
@@ -74,7 +74,7 @@
/** size of next free slot vector */
private int nextFreeSlotsSize;
- private boolean isWithBoundary(final LexicalContextNode node) {
+ private boolean isWithBoundary(final Object node) {
return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
}
@@ -102,7 +102,7 @@
}
@Override
- public <T extends LexicalContextNode> T pop(final T node) {
+ public <T extends Node> T pop(final T node) {
final T popped = super.pop(node);
if (isWithBoundary(node)) {
dynamicScopeCount--;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompileUnit.java Mon Feb 09 09:52:48 2015 -0800
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.codegen;
import java.io.Serializable;
+import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import jdk.nashorn.internal.ir.CompileUnitHolder;
@@ -113,7 +114,7 @@
* @param clazz class with code for this compile unit
*/
void setCode(final Class<?> clazz) {
- clazz.getClass(); // null check
+ Objects.requireNonNull(clazz);
this.clazz = clazz;
// Revisit this - refactor to avoid null-ed out non-final fields
// null out emitter
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java Mon Feb 09 09:52:48 2015 -0800
@@ -62,6 +62,7 @@
import jdk.nashorn.internal.ir.JoinPredecessor;
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
@@ -529,8 +530,7 @@
return false;
}
assertTypeStackIsEmpty();
- final BreakableNode target = jump.getTarget(lc);
- jumpToLabel(jump, jump.getTargetLabel(target), getBreakTargetTypes(target));
+ jumpToLabel(jump, jump.getTargetLabel(lc), getBreakTargetTypes(jump.getPopScopeLimit(lc)));
doesNotContinueSequentially();
return false;
}
@@ -784,6 +784,11 @@
}
@Override
+ public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ return enterJumpStatement(jumpToInlinedFinally);
+ }
+
+ @Override
public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
if (literalNode instanceof ArrayLiteralNode) {
final List<Expression> expressions = ((ArrayLiteralNode)literalNode).getElementExpressions();
@@ -1042,6 +1047,17 @@
}
doesNotContinueSequentially();
+ for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+ final Block finallyBody = TryNode.getLabelledInlinedFinallyBlock(inlinedFinally);
+ joinOnLabel(finallyBody.getEntryLabel());
+ // NOTE: the jump to inlined finally can end up in dead code, so it is not necessarily reachable.
+ if (reachable) {
+ finallyBody.accept(this);
+ // All inlined finallies end with a jump or a return
+ assert !reachable;
+ }
+ }
+
joinOnLabel(catchLabel);
for(final CatchNode catchNode: tryNode.getCatches()) {
final IdentNode exception = catchNode.getException();
@@ -1125,7 +1141,7 @@
return false;
};
- private Map<Symbol, LvarType> getBreakTargetTypes(final BreakableNode target) {
+ private Map<Symbol, LvarType> getBreakTargetTypes(final LexicalContextNode target) {
// Remove symbols defined in the the blocks that are being broken out of.
Map<Symbol, LvarType> types = localVariableTypes;
for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
@@ -1380,7 +1396,11 @@
if(node instanceof JoinPredecessor) {
final JoinPredecessor original = joinPredecessors.pop();
assert original.getClass() == node.getClass() : original.getClass().getName() + "!=" + node.getClass().getName();
- return (Node)setLocalVariableConversion(original, (JoinPredecessor)node);
+ final JoinPredecessor newNode = setLocalVariableConversion(original, (JoinPredecessor)node);
+ if (newNode instanceof LexicalContextNode) {
+ lc.replace((LexicalContextNode)node, (LexicalContextNode)newNode);
+ }
+ return (Node)newNode;
}
return node;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java Mon Feb 09 09:52:48 2015 -0800
@@ -56,9 +56,11 @@
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
import jdk.nashorn.internal.ir.LoopNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ReturnNode;
@@ -115,7 +117,7 @@
for (final Statement statement : statements) {
if (!terminated) {
newStatements.add(statement);
- if (statement.isTerminal() || statement instanceof BreakNode || statement instanceof ContinueNode) { //TODO hasGoto? But some Loops are hasGoto too - why?
+ if (statement.isTerminal() || statement instanceof JumpStatement) { //TODO hasGoto? But some Loops are hasGoto too - why?
terminated = true;
}
} else {
@@ -183,6 +185,12 @@
}
@Override
+ public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ addStatement(jumpToInlinedFinally);
+ return false;
+ }
+
+ @Override
public boolean enterEmptyNode(final EmptyNode emptyNode) {
return false;
}
@@ -318,8 +326,9 @@
return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
}
- private static Node ensureUniqueNamesIn(final Node node) {
- return node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+ @SuppressWarnings("unchecked")
+ private static <T extends Node> T ensureUniqueNamesIn(final T node) {
+ return (T)node.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public Node leaveFunctionNode(final FunctionNode functionNode) {
final String name = functionNode.getName();
@@ -333,15 +342,15 @@
});
}
- private static List<Statement> copyFinally(final Block finallyBody) {
+ private static Block createFinallyBlock(final Block finallyBody) {
final List<Statement> newStatements = new ArrayList<>();
for (final Statement statement : finallyBody.getStatements()) {
- newStatements.add((Statement)ensureUniqueNamesIn(statement));
+ newStatements.add(statement);
if (statement.hasTerminalFlags()) {
- return newStatements;
+ break;
}
}
- return newStatements;
+ return finallyBody.setStatements(null, newStatements);
}
private Block catchAllBlock(final TryNode tryNode) {
@@ -367,28 +376,24 @@
return new IdentNode(functionNode.getToken(), functionNode.getFinish(), cc.symbolName());
}
- private static boolean isTerminal(final List<Statement> statements) {
- return !statements.isEmpty() && statements.get(statements.size() - 1).hasTerminalFlags();
+ private static boolean isTerminalFinally(final Block finallyBlock) {
+ return finallyBlock.getLastStatement().hasTerminalFlags();
}
/**
* Splice finally code into all endpoints of a trynode
* @param tryNode the try node
- * @param rethrows list of rethrowing throw nodes from synthetic catch blocks
+ * @param rethrow the rethrowing throw nodes from the synthetic catch block
* @param finallyBody the code in the original finally block
* @return new try node after splicing finally code (same if nop)
*/
- private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
+ private TryNode spliceFinally(final TryNode tryNode, final ThrowNode rethrow, final Block finallyBody) {
assert tryNode.getFinallyBody() == null;
+ final Block finallyBlock = createFinallyBlock(finallyBody);
+ final ArrayList<Block> inlinedFinallies = new ArrayList<>();
+ final FunctionNode fn = lc.getCurrentFunction();
final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
- final List<Node> insideTry = new ArrayList<>();
-
- @Override
- public boolean enterDefault(final Node node) {
- insideTry.add(node);
- return true;
- }
@Override
public boolean enterFunctionNode(final FunctionNode functionNode) {
@@ -398,12 +403,8 @@
@Override
public Node leaveThrowNode(final ThrowNode throwNode) {
- if (rethrows.contains(throwNode)) {
- final List<Statement> newStatements = copyFinally(finallyBody);
- if (!isTerminal(newStatements)) {
- newStatements.add(throwNode);
- }
- return BlockStatement.createReplacement(throwNode, newStatements);
+ if (rethrow == throwNode) {
+ return new BlockStatement(prependFinally(finallyBlock, throwNode));
}
return throwNode;
}
@@ -419,58 +420,94 @@
}
private Node leaveJumpStatement(final JumpStatement jump) {
- return copy(jump, (Node)jump.getTarget(Lower.this.lc));
+ // NOTE: leaveJumpToInlinedFinally deliberately does not delegate to this method, only break and
+ // continue are edited. JTIF nodes should not be changed, rather the surroundings of
+ // break/continue/return that were moved into the inlined finally block itself will be changed.
+
+ // If this visitor's lc doesn't find the target of the jump, it means it's external to the try block.
+ if (jump.getTarget(lc) == null) {
+ return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, jump));
+ }
+ return jump;
}
@Override
public Node leaveReturnNode(final ReturnNode returnNode) {
- final Expression expr = returnNode.getExpression();
- final List<Statement> newStatements = new ArrayList<>();
-
- final Expression resultNode;
- if (expr != null) {
- //we need to evaluate the result of the return in case it is complex while
- //still in the try block, store it in a result value and return it afterwards
- resultNode = new IdentNode(Lower.this.compilerConstant(RETURN));
- newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+ final Expression expr = returnNode.getExpression();
+ if (isTerminalFinally(finallyBlock)) {
+ if (expr == null) {
+ // Terminal finally; no return expression.
+ return createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock));
+ }
+ // Terminal finally; has a return expression.
+ final List<Statement> newStatements = new ArrayList<>(2);
+ final int retLineNumber = returnNode.getLineNumber();
+ final long retToken = returnNode.getToken();
+ // Expression is evaluated for side effects.
+ newStatements.add(new ExpressionStatement(retLineNumber, retToken, returnNode.getFinish(), expr));
+ newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, ensureUniqueNamesIn(finallyBlock)));
+ return new BlockStatement(retLineNumber, new Block(retToken, finallyBlock.getFinish(), newStatements));
+ } else if (expr == null || expr instanceof PrimitiveLiteralNode<?> || (expr instanceof IdentNode && RETURN.symbolName().equals(((IdentNode)expr).getName()))) {
+ // Nonterminal finally; no return expression, or returns a primitive literal, or returns :return.
+ // Just move the return expression into the finally block.
+ return createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode));
} else {
- resultNode = null;
+ // We need to evaluate the result of the return in case it is complex while still in the try block,
+ // store it in :return, and return it afterwards.
+ final List<Statement> newStatements = new ArrayList<>();
+ final int retLineNumber = returnNode.getLineNumber();
+ final long retToken = returnNode.getToken();
+ final int retFinish = returnNode.getFinish();
+ final Expression resultNode = new IdentNode(expr.getToken(), expr.getFinish(), RETURN.symbolName());
+ // ":return = <expr>;"
+ newStatements.add(new ExpressionStatement(retLineNumber, retToken, retFinish, new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+ // inline finally and end it with "return :return;"
+ newStatements.add(createJumpToInlinedFinally(fn, inlinedFinallies, prependFinally(finallyBlock, returnNode.setExpression(resultNode))));
+ return new BlockStatement(retLineNumber, new Block(retToken, retFinish, newStatements));
}
-
- newStatements.addAll(copyFinally(finallyBody));
- if (!isTerminal(newStatements)) {
- newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode));
- }
-
- return BlockStatement.createReplacement(returnNode, lc.getCurrentBlock().getFinish(), newStatements);
- }
-
- private Node copy(final Statement endpoint, final Node targetNode) {
- if (!insideTry.contains(targetNode)) {
- final List<Statement> newStatements = copyFinally(finallyBody);
- if (!isTerminal(newStatements)) {
- newStatements.add(endpoint);
- }
- return BlockStatement.createReplacement(endpoint, tryNode.getFinish(), newStatements);
- }
- return endpoint;
}
});
-
- addStatement(newTryNode);
- for (final Node statement : finallyBody.getStatements()) {
- addStatement((Statement)statement);
- }
+ addStatement(inlinedFinallies.isEmpty() ? newTryNode : newTryNode.setInlinedFinallies(lc, inlinedFinallies));
+ // TODO: if finallyStatement is terminal, we could just have sites of inlined finallies jump here.
+ addStatement(new BlockStatement(finallyBlock));
return newTryNode;
}
+ private static JumpToInlinedFinally createJumpToInlinedFinally(final FunctionNode fn, final List<Block> inlinedFinallies, final Block finallyBlock) {
+ final String labelName = fn.uniqueName(":finally");
+ final long token = finallyBlock.getToken();
+ final int finish = finallyBlock.getFinish();
+ inlinedFinallies.add(new Block(token, finish, new LabelNode(finallyBlock.getFirstStatementLineNumber(),
+ token, finish, labelName, finallyBlock)));
+ return new JumpToInlinedFinally(labelName);
+ }
+
+ private static Block prependFinally(final Block finallyBlock, final Statement statement) {
+ final Block inlinedFinally = ensureUniqueNamesIn(finallyBlock);
+ if (isTerminalFinally(finallyBlock)) {
+ return inlinedFinally;
+ }
+ final List<Statement> stmts = inlinedFinally.getStatements();
+ final List<Statement> newStmts = new ArrayList<>(stmts.size() + 1);
+ newStmts.addAll(stmts);
+ newStmts.add(statement);
+ return new Block(inlinedFinally.getToken(), statement.getFinish(), newStmts);
+ }
+
@Override
public Node leaveTryNode(final TryNode tryNode) {
final Block finallyBody = tryNode.getFinallyBody();
+ TryNode newTryNode = tryNode.setFinallyBody(lc, null);
- if (finallyBody == null) {
- return addStatement(ensureUnconditionalCatch(tryNode));
+ // No finally or empty finally
+ if (finallyBody == null || finallyBody.getStatementCount() == 0) {
+ final List<CatchNode> catches = newTryNode.getCatches();
+ if (catches == null || catches.isEmpty()) {
+ // A completely degenerate try block: empty finally, no catches. Replace it with try body.
+ return addStatement(new BlockStatement(tryNode.getBody()));
+ }
+ return addStatement(ensureUnconditionalCatch(newTryNode));
}
/*
@@ -496,11 +533,9 @@
* now splice in finally code wherever needed
*
*/
- TryNode newTryNode;
-
final Block catchAll = catchAllBlock(tryNode);
- final List<ThrowNode> rethrows = new ArrayList<>();
+ final List<ThrowNode> rethrows = new ArrayList<>(1);
catchAll.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterThrowNode(final ThrowNode throwNode) {
@@ -510,20 +545,18 @@
});
assert rethrows.size() == 1;
- if (tryNode.getCatchBlocks().isEmpty()) {
- newTryNode = tryNode.setFinallyBody(null);
- } else {
- final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), ensureUnconditionalCatch(tryNode.setFinallyBody(null)));
- newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
+ if (!tryNode.getCatchBlocks().isEmpty()) {
+ final Block outerBody = new Block(newTryNode.getToken(), newTryNode.getFinish(), ensureUnconditionalCatch(newTryNode));
+ newTryNode = newTryNode.setBody(lc, outerBody).setCatchBlocks(lc, null);
}
- newTryNode = newTryNode.setCatchBlocks(Arrays.asList(catchAll)).setFinallyBody(null);
+ newTryNode = newTryNode.setCatchBlocks(lc, Arrays.asList(catchAll));
/*
* Now that the transform is done, we have to go into the try and splice
* the finally block in front of any statement that is outside the try
*/
- return spliceFinally(newTryNode, rethrows, finallyBody);
+ return (TryNode)lc.replace(tryNode, spliceFinally(newTryNode, rethrows.get(0), finallyBody));
}
private TryNode ensureUnconditionalCatch(final TryNode tryNode) {
@@ -535,7 +568,7 @@
final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks());
newCatchBlocks.add(catchAllBlock(tryNode));
- return tryNode.setCatchBlocks(newCatchBlocks);
+ return tryNode.setCatchBlocks(lc, newCatchBlocks);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java Mon Feb 09 09:52:48 2015 -0800
@@ -52,6 +52,7 @@
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ReturnNode;
@@ -359,6 +360,11 @@
return leaveJumpNode(continueNode);
}
+ @Override
+ public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ return leaveJumpNode(jumpToInlinedFinally);
+ }
+
private JumpStatement leaveJumpNode(final JumpStatement jump) {
if (inSplitNode()) {
final SplitState splitState = getCurrentSplitState();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java Mon Feb 09 09:52:48 2015 -0800
@@ -40,6 +40,7 @@
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
@@ -197,6 +198,12 @@
return indexNode;
}
+ @Override
+ public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ weight += BREAK_WEIGHT;
+ return jumpToInlinedFinally;
+ }
+
@SuppressWarnings("rawtypes")
@Override
public boolean enterLiteralNode(final LiteralNode literalNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java Mon Feb 09 09:52:48 2015 -0800
@@ -322,6 +322,14 @@
}
/**
+ * Returns the last statement in the block.
+ * @return the last statement in the block, or null if the block has no statements.
+ */
+ public Statement getLastStatement() {
+ return statements.isEmpty() ? null : statements.get(statements.size() - 1);
+ }
+
+ /**
* Reset the statement list for this block
*
* @param lc lexical context
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockLexicalContext.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockLexicalContext.java Mon Feb 09 09:52:48 2015 -0800
@@ -74,7 +74,7 @@
@SuppressWarnings("unchecked")
@Override
- public <T extends LexicalContextNode> T pop(final T node) {
+ public <T extends Node> T pop(final T node) {
T expected = node;
if (node instanceof Block) {
final List<Statement> newStatements = popStatements();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockStatement.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BlockStatement.java Mon Feb 09 09:52:48 2015 -0800
@@ -40,6 +40,15 @@
/**
* Constructor
*
+ * @param block the block to execute
+ */
+ public BlockStatement(final Block block) {
+ this(block.getFirstStatementLineNumber(), block);
+ }
+
+ /**
+ * Constructor
+ *
* @param lineNumber line number
* @param block the block to execute
*/
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BreakNode.java Mon Feb 09 09:52:48 2015 -0800
@@ -77,7 +77,7 @@
}
@Override
- public Label getTargetLabel(final BreakableNode target) {
+ Label getTargetLabel(final BreakableNode target) {
return target.getBreakLabel();
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ContinueNode.java Mon Feb 09 09:52:48 2015 -0800
@@ -78,7 +78,7 @@
}
@Override
- public Label getTargetLabel(final BreakableNode target) {
+ Label getTargetLabel(final BreakableNode target) {
return ((LoopNode)target).getContinueLabel();
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpStatement.java Mon Feb 09 09:52:48 2015 -0800
@@ -101,7 +101,26 @@
* @throws ClassCastException if invoked on the kind of breakable node that this jump statement is not prepared to
* handle.
*/
- public abstract Label getTargetLabel(final BreakableNode target);
+ abstract Label getTargetLabel(final BreakableNode target);
+
+ /**
+ * Returns the label this jump statement targets.
+ * @param lc the lexical context
+ * @return the label this jump statement targets.
+ */
+ public Label getTargetLabel(final LexicalContext lc) {
+ return getTargetLabel(getTarget(lc));
+ }
+
+ /**
+ * Returns the limit node for popping scopes when this jump statement is effected.
+ * @param lc the current lexical context
+ * @return the limit node for popping scopes when this jump statement is effected.
+ */
+ public LexicalContextNode getPopScopeLimit(final LexicalContext lc) {
+ // In most cases (break and continue) this is equal to the target.
+ return getTarget(lc);
+ }
@Override
public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/JumpToInlinedFinally.java Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.Objects;
+import jdk.nashorn.internal.codegen.Label;
+import jdk.nashorn.internal.ir.annotations.Immutable;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for synthetic jump into an inlined finally statement.
+ */
+@Immutable
+public final class JumpToInlinedFinally extends JumpStatement {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor
+ *
+ * @param labelName label name for inlined finally block
+ */
+ public JumpToInlinedFinally(final String labelName) {
+ super(NO_LINE_NUMBER, NO_TOKEN, NO_FINISH, Objects.requireNonNull(labelName));
+ }
+
+ private JumpToInlinedFinally(final JumpToInlinedFinally breakNode, final LocalVariableConversion conversion) {
+ super(breakNode, conversion);
+ }
+
+ @Override
+ public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ if (visitor.enterJumpToInlinedFinally(this)) {
+ return visitor.leaveJumpToInlinedFinally(this);
+ }
+
+ return this;
+ }
+
+ @Override
+ JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+ return new JumpToInlinedFinally(this, conversion);
+ }
+
+ @Override
+ String getStatementName() {
+ return ":jumpToInlinedFinally";
+ }
+
+ @Override
+ public Block getTarget(final LexicalContext lc) {
+ return lc.getInlinedFinally(getLabelName());
+ }
+
+ @Override
+ public TryNode getPopScopeLimit(final LexicalContext lc) {
+ // Returns the try node to which this jump's target belongs. This will make scope popping also pop the scope
+ // for the body of the try block, if it needs scope.
+ return lc.getTryNodeForInlinedFinally(getLabelName());
+ }
+
+ @Override
+ Label getTargetLabel(final BreakableNode target) {
+ assert target != null;
+ // We're jumping to the entry of the inlined finally block
+ return ((Block)target).getEntryLabel();
+ }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContext.java Mon Feb 09 09:52:48 2015 -0800
@@ -190,7 +190,7 @@
* @return the node that was popped
*/
@SuppressWarnings("unchecked")
- public <T extends LexicalContextNode> T pop(final T node) {
+ public <T extends Node> T pop(final T node) {
--sp;
final LexicalContextNode popped = stack[sp];
stack[sp] = null;
@@ -469,7 +469,7 @@
* scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode
* method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location
* and the break/continue target.
- * @param until node to stop counting at. Must be within the current function
+ * @param until node to stop counting at. Must be within the current function
* @return number of with scopes encountered in the context
*/
public int getScopeNestingLevelTo(final LexicalContextNode until) {
@@ -565,11 +565,41 @@
}
/**
+ * Find the inlined finally block node corresponding to this label.
+ * @param labelName label name to search for. Must not be null.
+ * @return closest inlined finally block with the given label
+ */
+ public Block getInlinedFinally(final String labelName) {
+ for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+ final Block inlinedFinally = iter.next().getInlinedFinally(labelName);
+ if (inlinedFinally != null) {
+ return inlinedFinally;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find the try node for an inlined finally block corresponding to this label.
+ * @param labelName label name to search for. Must not be null.
+ * @return the try node to which the labelled inlined finally block belongs.
+ */
+ public TryNode getTryNodeForInlinedFinally(final String labelName) {
+ for (final NodeIterator<TryNode> iter = new NodeIterator<>(TryNode.class); iter.hasNext(); ) {
+ final TryNode tryNode = iter.next();
+ if (tryNode.getInlinedFinally(labelName) != null) {
+ return tryNode;
+ }
+ }
+ return null;
+ }
+
+ /**
* Check the lexical context for a given label node by name
* @param name name of the label
* @return LabelNode if found, null otherwise
*/
- public LabelNode findLabel(final String name) {
+ private LabelNode findLabel(final String name) {
for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
final LabelNode next = iter.next();
if (next.getLabelName().equals(name)) {
@@ -592,6 +622,12 @@
return true;
} else if (next == target) {
return false;
+ } else if (next instanceof TryNode) {
+ for(final Block inlinedFinally: ((TryNode)next).getInlinedFinallies()) {
+ if (TryNode.getLabelledInlinedFinallyBlock(inlinedFinally) == target) {
+ return false;
+ }
+ }
}
}
throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContextNode.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LexicalContextNode.java Mon Feb 09 09:52:48 2015 -0800
@@ -54,8 +54,8 @@
static Node accept(final LexicalContextNode node, final NodeVisitor<? extends LexicalContext> visitor) {
final LexicalContext lc = visitor.getLexicalContext();
lc.push(node);
- final LexicalContextNode newNode = (LexicalContextNode)node.accept(lc, visitor);
- return (Node)lc.pop(newNode);
+ final Node newNode = node.accept(lc, visitor);
+ return lc.pop(newNode);
}
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/OptimisticLexicalContext.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/OptimisticLexicalContext.java Mon Feb 09 09:52:48 2015 -0800
@@ -115,7 +115,7 @@
}
@Override
- public <T extends LexicalContextNode> T pop(final T node) {
+ public <T extends Node> T pop(final T node) {
final T popped = super.pop(node);
if (isEnabled) {
if(node instanceof FunctionNode) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TryNode.java Mon Feb 09 09:52:48 2015 -0800
@@ -27,7 +27,9 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import jdk.nashorn.internal.ir.annotations.Immutable;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -35,7 +37,7 @@
* IR representation of a TRY statement.
*/
@Immutable
-public final class TryNode extends Statement implements JoinPredecessor {
+public final class TryNode extends LexicalContextStatement implements JoinPredecessor {
private static final long serialVersionUID = 1L;
/** Try statements. */
@@ -47,12 +49,24 @@
/** Finally clause. */
private final Block finallyBody;
+ /**
+ * List of inlined finally blocks. The structure of every inlined finally is:
+ * Block(LabelNode(label, Block(finally-statements, (JumpStatement|ReturnNode)?))).
+ * That is, the block has a single LabelNode statement with the label and a block containing the
+ * statements of the inlined finally block with the jump or return statement appended (if the finally
+ * block was not terminal; the original jump/return is simply ignored if the finally block itself
+ * terminates). The reason for this somewhat strange arrangement is that we didn't want to create a
+ * separate class for the (label, BlockStatement pair) but rather reused the already available LabelNode.
+ * However, if we simply used List<LabelNode> without wrapping the label nodes in an additional Block,
+ * that would've thrown off visitors relying on BlockLexicalContext -- same reason why we never use
+ * Statement as the type of bodies of e.g. IfNode, WhileNode etc. but rather blockify them even when they're
+ * single statements.
+ */
+ private final List<Block> inlinedFinallies;
+
/** Exception symbol. */
private Symbol exception;
- /** Catchall exception for finally expansion, where applicable */
- private Symbol finallyCatchAll;
-
private final LocalVariableConversion conversion;
/**
@@ -71,21 +85,23 @@
this.catchBlocks = catchBlocks;
this.finallyBody = finallyBody;
this.conversion = null;
+ this.inlinedFinallies = Collections.emptyList();
}
- private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion) {
+ private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion, final List<Block> inlinedFinallies) {
super(tryNode);
this.body = body;
this.catchBlocks = catchBlocks;
this.finallyBody = finallyBody;
this.conversion = conversion;
+ this.inlinedFinallies = inlinedFinallies;
this.exception = tryNode.exception;
}
@Override
public Node ensureUniqueLabels(final LexicalContext lc) {
//try nodes are never in lex context
- return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
}
@Override
@@ -106,16 +122,16 @@
* @param visitor IR navigating visitor.
*/
@Override
- public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+ public Node accept(final LexicalContext lc, NodeVisitor<? extends LexicalContext> visitor) {
if (visitor.enterTryNode(this)) {
// Need to do finallybody first for termination analysis. TODO still necessary?
final Block newFinallyBody = finallyBody == null ? null : (Block)finallyBody.accept(visitor);
final Block newBody = (Block)body.accept(visitor);
return visitor.leaveTryNode(
- setBody(newBody).
- setFinallyBody(newFinallyBody).
- setCatchBlocks(Node.accept(visitor, catchBlocks)).
- setFinallyCatchAll(finallyCatchAll));
+ setBody(lc, newBody).
+ setFinallyBody(lc, newFinallyBody).
+ setCatchBlocks(lc, Node.accept(visitor, catchBlocks)).
+ setInlinedFinallies(lc, Node.accept(visitor, inlinedFinallies)));
}
return this;
@@ -136,14 +152,15 @@
/**
* Reset the body of this try block
+ * @param lc current lexical context
* @param body new body
* @return new TryNode or same if unchanged
*/
- public TryNode setBody(final Block body) {
+ public TryNode setBody(final LexicalContext lc, final Block body) {
if (this.body == body) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
}
/**
@@ -172,14 +189,15 @@
/**
* Set the catch blocks of this try
+ * @param lc current lexical context
* @param catchBlocks list of catch blocks
* @return new TryNode or same if unchanged
*/
- public TryNode setCatchBlocks(final List<Block> catchBlocks) {
+ public TryNode setCatchBlocks(final LexicalContext lc, final List<Block> catchBlocks) {
if (this.catchBlocks == catchBlocks) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
}
/**
@@ -200,27 +218,6 @@
}
/**
- * Get the catch all symbol for this try block
- * @return catch all symbol
- */
- public Symbol getFinallyCatchAll() {
- return this.finallyCatchAll;
- }
-
- /**
- * If a finally block exists, the synthetic catchall needs another symbol to
- * store its throwable
- * @param finallyCatchAll a symbol for the finally catch all exception
- * @return new TryNode or same if unchanged
- *
- * TODO can this still be stateful?
- */
- public TryNode setFinallyCatchAll(final Symbol finallyCatchAll) {
- this.finallyCatchAll = finallyCatchAll;
- return this;
- }
-
- /**
* Get the body of the finally clause for this try
* @return finally body, or null if no finally
*/
@@ -229,15 +226,87 @@
}
/**
+ * Get the inlined finally block with the given label name. This returns the actual finally block in the
+ * {@link LabelNode}, not the outer wrapper block for the {@link LabelNode}.
+ * @param labelName the name of the inlined finally's label
+ * @return the requested finally block, or null if no finally block's label matches the name.
+ */
+ public Block getInlinedFinally(final String labelName) {
+ for(final Block inlinedFinally: inlinedFinallies) {
+ final LabelNode labelNode = getInlinedFinallyLabelNode(inlinedFinally);
+ if (labelNode.getLabelName().equals(labelName)) {
+ return labelNode.getBody();
+ }
+ }
+ return null;
+ }
+
+ private static LabelNode getInlinedFinallyLabelNode(final Block inlinedFinally) {
+ return (LabelNode)inlinedFinally.getStatements().get(0);
+ }
+
+ /**
+ * Given an outer wrapper block for the {@link LabelNode} as returned by {@link #getInlinedFinallies()},
+ * returns its actual inlined finally block.
+ * @param inlinedFinally the outer block for inlined finally, as returned as an element of
+ * {@link #getInlinedFinallies()}.
+ * @return the block contained in the {@link LabelNode} contained in the passed block.
+ */
+ public static Block getLabelledInlinedFinallyBlock(final Block inlinedFinally) {
+ return getInlinedFinallyLabelNode(inlinedFinally).getBody();
+ }
+
+ /**
+ * Returns a list of inlined finally blocks. Note that this returns a list of {@link Block}s such that each one of
+ * them has a single {@link LabelNode}, which in turn contains the label name for the finally block and the
+ * actual finally block. To safely extract the actual finally block, use
+ * {@link #getLabelledInlinedFinallyBlock(Block)}.
+ * @return a list of inlined finally blocks.
+ */
+ public List<Block> getInlinedFinallies() {
+ return Collections.unmodifiableList(inlinedFinallies);
+ }
+
+ /**
* Set the finally body of this try
+ * @param lc current lexical context
* @param finallyBody new finally body
* @return new TryNode or same if unchanged
*/
- public TryNode setFinallyBody(final Block finallyBody) {
+ public TryNode setFinallyBody(final LexicalContext lc, final Block finallyBody) {
if (this.finallyBody == finallyBody) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ }
+
+ /**
+ * Set the inlined finally blocks of this try. Each element should be a block with a single statement that is a
+ * {@link LabelNode} with a unique label, and the block within the label node should contain the actual inlined
+ * finally block.
+ * @param lc current lexical context
+ * @param inlinedFinallies list of inlined finally blocks
+ * @return new TryNode or same if unchanged
+ */
+ public TryNode setInlinedFinallies(final LexicalContext lc, final List<Block> inlinedFinallies) {
+ if (this.inlinedFinallies == inlinedFinallies) {
+ return this;
+ }
+ assert checkInlinedFinallies(inlinedFinallies);
+ return Node.replaceInLexicalContext(lc, this, new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies));
+ }
+
+ private static boolean checkInlinedFinallies(final List<Block> inlinedFinallies) {
+ if (!inlinedFinallies.isEmpty()) {
+ final Set<String> labels = new HashSet<>();
+ for (final Block inlinedFinally : inlinedFinallies) {
+ final List<Statement> stmts = inlinedFinally.getStatements();
+ assert stmts.size() == 1;
+ final LabelNode ln = getInlinedFinallyLabelNode(inlinedFinally);
+ assert labels.add(ln.getLabelName()); // unique label
+ }
+ }
+ return true;
}
@Override
@@ -245,7 +314,7 @@
if(this.conversion == conversion) {
return this;
}
- return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+ return new TryNode(this, body, catchBlocks, finallyBody, conversion, inlinedFinallies);
}
@Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/PrintVisitor.java Mon Feb 09 09:52:48 2015 -0800
@@ -391,6 +391,9 @@
finallyBody.accept(this);
}
+ for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
+ inlinedFinally.accept(this);
+ }
return false;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java Mon Feb 09 09:52:48 2015 -0800
@@ -43,6 +43,7 @@
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LiteralNode;
@@ -473,6 +474,26 @@
}
/**
+ * Callback for entering a JumpToInlinedFinally
+ *
+ * @param jumpToInlinedFinally the node
+ * @return true if traversal should continue and node children be traversed, false otherwise
+ */
+ public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ return enterDefault(jumpToInlinedFinally);
+ }
+
+ /**
+ * Callback for leaving a JumpToInlinedFinally
+ *
+ * @param jumpToInlinedFinally the node
+ * @return processed node, which will replace the original one, or the original node
+ */
+ public Node leaveJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
+ return leaveDefault(jumpToInlinedFinally);
+ }
+
+ /**
* Callback for entering a LabelNode
*
* @param labelNode the node
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Mon Feb 09 09:52:48 2015 -0800
@@ -41,6 +41,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import javax.script.ScriptContext;
@@ -463,8 +464,7 @@
sm.checkPermission(new RuntimePermission(Context.NASHORN_CREATE_GLOBAL));
}
- // null check on context
- context.getClass();
+ Objects.requireNonNull(context);
return $nasgenmap$;
}
@@ -488,7 +488,7 @@
*/
public static Global instance() {
final Global global = Context.getGlobal();
- global.getClass(); // null check
+ Objects.requireNonNull(global);
return global;
}
@@ -580,13 +580,15 @@
} else if (obj instanceof String || obj instanceof ConsString) {
return new NativeString((CharSequence)obj, this);
} else if (obj instanceof Object[]) { // extension
- return new NativeArray((Object[])obj);
+ return new NativeArray(ArrayData.allocate((Object[])obj), this);
} else if (obj instanceof double[]) { // extension
- return new NativeArray((double[])obj);
+ return new NativeArray(ArrayData.allocate((double[])obj), this);
} else if (obj instanceof long[]) {
- return new NativeArray((long[])obj);
+ return new NativeArray(ArrayData.allocate((long[])obj), this);
} else if (obj instanceof int[]) {
- return new NativeArray((int[])obj);
+ return new NativeArray(ArrayData.allocate((int[]) obj), this);
+ } else if (obj instanceof ArrayData) {
+ return new NativeArray((ArrayData) obj, this);
} else {
// FIXME: more special cases? Map? List?
return obj;
@@ -1028,14 +1030,19 @@
}
// builtin prototype accessors
+
+ /**
+ * Get the builtin Object prototype.
+ * @return the object prototype.
+ */
+ public ScriptObject getObjectPrototype() {
+ return ScriptFunction.getPrototype(builtinObject);
+ }
+
ScriptObject getFunctionPrototype() {
return ScriptFunction.getPrototype(builtinFunction);
}
- ScriptObject getObjectPrototype() {
- return ScriptFunction.getPrototype(builtinObject);
- }
-
ScriptObject getArrayPrototype() {
return ScriptFunction.getPrototype(builtinArray);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Mon Feb 09 09:52:48 2015 -0800
@@ -120,9 +120,6 @@
this(ArrayData.allocate(array.length));
ArrayData arrayData = this.getArray();
- if (array.length > 0) {
- arrayData.ensure(array.length - 1);
- }
for (int index = 0; index < array.length; index++) {
final Object value = array[index];
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/JSONParser.java Mon Feb 09 09:52:48 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,38 +25,59 @@
package jdk.nashorn.internal.parser;
-import static jdk.nashorn.internal.parser.TokenType.COLON;
-import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
-import static jdk.nashorn.internal.parser.TokenType.EOF;
-import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
-import static jdk.nashorn.internal.parser.TokenType.RBRACE;
-import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
-import static jdk.nashorn.internal.parser.TokenType.STRING;
import java.util.ArrayList;
import java.util.List;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
-import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.ECMAErrors;
import jdk.nashorn.internal.runtime.ErrorManager;
+import jdk.nashorn.internal.runtime.JSErrorType;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.SpillProperty;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
+import jdk.nashorn.internal.scripts.JO;
+
+import static jdk.nashorn.internal.parser.TokenType.STRING;
/**
* Parses JSON text and returns the corresponding IR node. This is derived from the objectLiteral production of the main parser.
*
* See: 15.12.1.2 The JSON Syntactic Grammar
*/
-public class JSONParser extends AbstractParser {
+public class JSONParser {
+
+ final private String source;
+ final private Global global;
+ final int length;
+ int pos = 0;
+
+ private static PropertyMap EMPTY_MAP = PropertyMap.newMap();
+
+ private static final int EOF = -1;
+
+ private static final String TRUE = "true";
+ private static final String FALSE = "false";
+ private static final String NULL = "null";
+
+ private static final int STATE_EMPTY = 0;
+ private static final int STATE_ELEMENT_PARSED = 1;
+ private static final int STATE_COMMA_PARSED = 2;
/**
* Constructor
* @param source the source
- * @param errors the error manager
+ * @param global the global object
*/
- public JSONParser(final Source source, final ErrorManager errors) {
- super(source, errors, false, 0);
+ public JSONParser(final String source, final Global global ) {
+ this.source = source;
+ this.global = global;
+ this.length = source.length();
}
/**
@@ -114,329 +135,409 @@
}
/**
- * Public parsed method - start lexing a new token stream for
- * a JSON script
+ * Public parse method. Parse a string into a JSON object.
*
- * @return the JSON literal
+ * @return the parsed JSON Object
*/
- public Node parse() {
- stream = new TokenStream();
-
- lexer = new Lexer(source, stream) {
-
- @Override
- protected boolean skipComments() {
- return false;
- }
-
- @Override
- protected boolean isStringDelimiter(final char ch) {
- return ch == '\"';
- }
-
- // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONWhiteSpace
- @Override
- protected boolean isWhitespace(final char ch) {
- return Lexer.isJsonWhitespace(ch);
- }
-
- @Override
- protected boolean isEOL(final char ch) {
- return Lexer.isJsonEOL(ch);
- }
+ public Object parse() {
+ final Object value = parseLiteral();
+ skipWhiteSpace();
+ if (pos < length) {
+ throw expectedError(pos, "eof", toString(peek()));
+ }
+ return value;
+ }
- // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONNumber
- @Override
- protected void scanNumber() {
- // Record beginning of number.
- final int startPosition = position;
- // Assume value is a decimal.
- TokenType valueType = TokenType.DECIMAL;
-
- // floating point can't start with a "." with no leading digit before
- if (ch0 == '.') {
- error(Lexer.message("json.invalid.number"), STRING, position, limit);
- }
-
- // First digit of number.
- final int digit = convertDigit(ch0, 10);
-
- // skip first digit
- skip(1);
-
- if (digit != 0) {
- // Skip over remaining digits.
- while (convertDigit(ch0, 10) != -1) {
- skip(1);
- }
- }
-
- if (ch0 == '.' || ch0 == 'E' || ch0 == 'e') {
- // Must be a double.
- if (ch0 == '.') {
- // Skip period.
- skip(1);
+ private Object parseLiteral() {
+ skipWhiteSpace();
- boolean mantissa = false;
- // Skip mantissa.
- while (convertDigit(ch0, 10) != -1) {
- mantissa = true;
- skip(1);
- }
-
- if (! mantissa) {
- // no digit after "."
- error(Lexer.message("json.invalid.number"), STRING, position, limit);
- }
- }
-
- // Detect exponent.
- if (ch0 == 'E' || ch0 == 'e') {
- // Skip E.
- skip(1);
- // Detect and skip exponent sign.
- if (ch0 == '+' || ch0 == '-') {
- skip(1);
- }
- boolean exponent = false;
- // Skip exponent.
- while (convertDigit(ch0, 10) != -1) {
- exponent = true;
- skip(1);
- }
-
- if (! exponent) {
- // no digit after "E"
- error(Lexer.message("json.invalid.number"), STRING, position, limit);
- }
- }
-
- valueType = TokenType.FLOATING;
- }
-
- // Add number token.
- add(valueType, startPosition);
+ final int c = peek();
+ if (c == EOF) {
+ throw expectedError(pos, "json literal", "eof");
+ }
+ switch (c) {
+ case '{':
+ return parseObject();
+ case '[':
+ return parseArray();
+ case '"':
+ return parseString();
+ case 'f':
+ return parseKeyword(FALSE, Boolean.FALSE);
+ case 't':
+ return parseKeyword(TRUE, Boolean.TRUE);
+ case 'n':
+ return parseKeyword(NULL, null);
+ default:
+ if (isDigit(c) || c == '-') {
+ return parseNumber();
+ } else if (c == '.') {
+ throw numberError(pos);
+ } else {
+ throw expectedError(pos, "json literal", toString(c));
}
-
- // ECMA 15.12.1.1 The JSON Lexical Grammar - JSONEscapeCharacter
- @Override
- protected boolean isEscapeCharacter(final char ch) {
- switch (ch) {
- case '"':
- case '/':
- case '\\':
- case 'b':
- case 'f':
- case 'n':
- case 'r':
- case 't':
- // could be unicode escape
- case 'u':
- return true;
- default:
- return false;
- }
- }
- };
-
- k = -1;
-
- next();
-
- final Node resultNode = jsonLiteral();
- expect(EOF);
-
- return resultNode;
+ }
}
- @SuppressWarnings("fallthrough")
- private LiteralNode<?> getStringLiteral() {
- final LiteralNode<?> literal = getLiteral();
- final String str = (String)literal.getValue();
+ private Object parseObject() {
+ PropertyMap propertyMap = EMPTY_MAP;
+ ArrayData arrayData = ArrayData.EMPTY_ARRAY;
+ final ArrayList<Object> values = new ArrayList<>();
+ int state = STATE_EMPTY;
+
+ assert peek() == '{';
+ pos++;
+
+ while (pos < length) {
+ skipWhiteSpace();
+ final int c = peek();
- for (int i = 0; i < str.length(); i++) {
- final char ch = str.charAt(i);
- switch (ch) {
+ switch (c) {
+ case '"':
+ if (state == STATE_ELEMENT_PARSED) {
+ throw expectedError(pos - 1, ", or }", toString(c));
+ }
+ final String id = parseString();
+ expectColon();
+ final Object value = parseLiteral();
+ final int index = ArrayIndex.getArrayIndex(id);
+ if (ArrayIndex.isValidArrayIndex(index)) {
+ arrayData = addArrayElement(arrayData, index, value);
+ } else {
+ propertyMap = addObjectProperty(propertyMap, values, id, value);
+ }
+ state = STATE_ELEMENT_PARSED;
+ break;
+ case ',':
+ if (state != STATE_ELEMENT_PARSED) {
+ throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+ }
+ state = STATE_COMMA_PARSED;
+ pos++;
+ break;
+ case '}':
+ if (state == STATE_COMMA_PARSED) {
+ throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+ }
+ pos++;
+ return createObject(propertyMap, values, arrayData);
default:
- if (ch > 0x001f) {
- break;
- }
- case '"':
- case '\\':
- throw error(AbstractParser.message("unexpected.token", str));
+ throw expectedError(pos, ", or }", toString(c));
+ }
+ }
+ throw expectedError(pos, ", or }", "eof");
+ }
+
+ private static ArrayData addArrayElement(final ArrayData arrayData, final int index, final Object value) {
+ final long oldLength = arrayData.length();
+ final long longIndex = ArrayIndex.toLongIndex(index);
+ ArrayData newArrayData = arrayData;
+ if (longIndex >= oldLength) {
+ newArrayData = newArrayData.ensure(longIndex);
+ if (longIndex > oldLength) {
+ newArrayData = newArrayData.delete(oldLength, longIndex - 1);
+ }
+ }
+ return newArrayData.set(index, value, false);
+ }
+
+ private static PropertyMap addObjectProperty(final PropertyMap propertyMap, final List<Object> values,
+ final String id, final Object value) {
+ final Property oldProperty = propertyMap.findProperty(id);
+ final Property newProperty;
+ final PropertyMap newMap;
+ final Class<?> type = ObjectClassGenerator.OBJECT_FIELDS_ONLY ? Object.class : getType(value);
+
+ if (oldProperty != null) {
+ values.set(oldProperty.getSlot(), value);
+ newProperty = new SpillProperty(id, 0, oldProperty.getSlot());
+ newProperty.setType(type);
+ newMap = propertyMap.replaceProperty(oldProperty, newProperty);;
+ } else {
+ values.add(value);
+ newProperty = new SpillProperty(id, 0, propertyMap.size());
+ newProperty.setType(type);
+ newMap = propertyMap.addProperty(newProperty);
+ }
+
+ return newMap;
+ }
+
+ private Object createObject(final PropertyMap propertyMap, final List<Object> values, final ArrayData arrayData) {
+ final long[] primitiveSpill = new long[values.size()];
+ final Object[] objectSpill = new Object[values.size()];
+
+ for (final Property property : propertyMap.getProperties()) {
+ if (property.getType() == Object.class) {
+ objectSpill[property.getSlot()] = values.get(property.getSlot());
+ } else {
+ primitiveSpill[property.getSlot()] = ObjectClassGenerator.pack((Number) values.get(property.getSlot()));
}
}
- return literal;
+ final ScriptObject object = new JO(propertyMap, primitiveSpill, objectSpill);
+ object.setInitialProto(global.getObjectPrototype());
+ object.setArray(arrayData);
+ return object;
+ }
+
+ private static Class<?> getType(final Object value) {
+ if (value instanceof Integer) {
+ return int.class;
+ } else if (value instanceof Long) {
+ return long.class;
+ } else if (value instanceof Double) {
+ return double.class;
+ } else {
+ return Object.class;
+ }
+ }
+
+ private void expectColon() {
+ skipWhiteSpace();
+ final int n = next();
+ if (n != ':') {
+ throw expectedError(pos - 1, ":", toString(n));
+ }
}
- /**
- * Parse a JSON literal from the token stream
- * @return the JSON literal as a Node
- */
- private Expression jsonLiteral() {
- final long literalToken = token;
+ private Object parseArray() {
+ ArrayData arrayData = ArrayData.EMPTY_ARRAY;
+ int state = STATE_EMPTY;
- switch (type) {
- case STRING:
- return getStringLiteral();
- case ESCSTRING:
- case DECIMAL:
- case FLOATING:
- return getLiteral();
- case FALSE:
- next();
- return LiteralNode.newInstance(literalToken, finish, false);
- case TRUE:
- next();
- return LiteralNode.newInstance(literalToken, finish, true);
- case NULL:
- next();
- return LiteralNode.newInstance(literalToken, finish);
- case LBRACKET:
- return arrayLiteral();
- case LBRACE:
- return objectLiteral();
- /*
- * A.8.1 JSON Lexical Grammar
- *
- * JSONNumber :: See 15.12.1.1
- * -opt DecimalIntegerLiteral JSONFractionopt ExponentPartopt
- */
- case SUB:
- next();
+ assert peek() == '[';
+ pos++;
- final long realToken = token;
- final Object value = getValue();
-
- if (value instanceof Number) {
- next();
- return new UnaryNode(literalToken, LiteralNode.newInstance(realToken, finish, (Number)value));
- }
+ while (pos < length) {
+ skipWhiteSpace();
+ final int c = peek();
- throw error(AbstractParser.message("expected", "number", type.getNameOrType()));
- default:
- break;
- }
-
- throw error(AbstractParser.message("expected", "json literal", type.getNameOrType()));
- }
-
- /**
- * Parse an array literal from the token stream
- * @return the array literal as a Node
- */
- private LiteralNode<Expression[]> arrayLiteral() {
- // Unlike JavaScript array literals, elison is not permitted in JSON.
-
- // Capture LBRACKET token.
- final long arrayToken = token;
- // LBRACKET tested in caller.
- next();
-
- LiteralNode<Expression[]> result = null;
- // Prepare to accummulating elements.
- final List<Expression> elements = new ArrayList<>();
-
-loop:
- while (true) {
- switch (type) {
- case RBRACKET:
- next();
- result = LiteralNode.newInstance(arrayToken, finish, elements);
- break loop;
-
- case COMMARIGHT:
- next();
- // check for trailing comma - not allowed in JSON
- if (type == RBRACKET) {
- throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType()));
+ switch (c) {
+ case ',':
+ if (state != STATE_ELEMENT_PARSED) {
+ throw error(AbstractParser.message("trailing.comma.in.json"), pos);
}
+ state = STATE_COMMA_PARSED;
+ pos++;
break;
-
+ case ']':
+ if (state == STATE_COMMA_PARSED) {
+ throw error(AbstractParser.message("trailing.comma.in.json"), pos);
+ }
+ pos++;
+ return global.wrapAsObject(arrayData);
default:
- // Add expression element.
- elements.add(jsonLiteral());
- // Comma between array elements is mandatory in JSON.
- if (type != COMMARIGHT && type != RBRACKET) {
- throw error(AbstractParser.message("expected", ", or ]", type.getNameOrType()));
+ if (state == STATE_ELEMENT_PARSED) {
+ throw expectedError(pos, ", or ]", toString(c));
}
+ final long index = arrayData.length();
+ arrayData = arrayData.ensure(index).set((int) index, parseLiteral(), true);
+ state = STATE_ELEMENT_PARSED;
break;
}
}
- return result;
+ throw expectedError(pos, ", or ]", "eof");
}
- /**
- * Parse an object literal from the token stream
- * @return the object literal as a Node
- */
- private ObjectNode objectLiteral() {
- // Capture LBRACE token.
- final long objectToken = token;
- // LBRACE tested in caller.
- next();
+ private String parseString() {
+ // String buffer is only instantiated if string contains escape sequences.
+ int start = ++pos;
+ StringBuilder sb = null;
- // Prepare to accumulate elements.
- final List<PropertyNode> elements = new ArrayList<>();
+ while (pos < length) {
+ final int c = next();
+ if (c <= 0x1f) {
+ // Characters < 0x1f are not allowed in JSON strings.
+ throw syntaxError(pos, "String contains control character");
- // Create a block for the object literal.
-loop:
- while (true) {
- switch (type) {
- case RBRACE:
- next();
- break loop;
+ } else if (c == '\\') {
+ if (sb == null) {
+ sb = new StringBuilder(pos - start + 16);
+ }
+ sb.append(source, start, pos - 1);
+ sb.append(parseEscapeSequence());
+ start = pos;
- case COMMARIGHT:
- next();
- // check for trailing comma - not allowed in JSON
- if (type == RBRACE) {
- throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType()));
+ } else if (c == '"') {
+ if (sb != null) {
+ sb.append(source, start, pos - 1);
+ return sb.toString();
}
- break;
-
- default:
- // Get and add the next property.
- final PropertyNode property = propertyAssignment();
- elements.add(property);
-
- // Comma between property assigments is mandatory in JSON.
- if (type != RBRACE && type != COMMARIGHT) {
- throw error(AbstractParser.message("expected", ", or }", type.getNameOrType()));
- }
- break;
+ return source.substring(start, pos - 1);
}
}
- // Construct new object literal.
- return new ObjectNode(objectToken, finish, elements);
+ throw error(Lexer.message("missing.close.quote"), pos, length);
+ }
+
+ private char parseEscapeSequence() {
+ final int c = next();
+ switch (c) {
+ case '"':
+ return '"';
+ case '\\':
+ return '\\';
+ case '/':
+ return '/';
+ case 'b':
+ return '\b';
+ case 'f':
+ return '\f';
+ case 'n':
+ return '\n';
+ case 'r':
+ return '\r';
+ case 't':
+ return '\t';
+ case 'u':
+ return parseUnicodeEscape();
+ default:
+ throw error(Lexer.message("invalid.escape.char"), pos - 1, length);
+ }
+ }
+
+ private char parseUnicodeEscape() {
+ return (char) (parseHexDigit() << 12 | parseHexDigit() << 8 | parseHexDigit() << 4 | parseHexDigit());
+ }
+
+ private int parseHexDigit() {
+ final int c = next();
+ if (c >= '0' && c <= '9') {
+ return c - '0';
+ } else if (c >= 'A' && c <= 'F') {
+ return c + 10 - 'A';
+ } else if (c >= 'a' && c <= 'f') {
+ return c + 10 - 'a';
+ }
+ throw error(Lexer.message("invalid.hex"), pos - 1, length);
+ }
+
+ private boolean isDigit(final int c) {
+ return c >= '0' && c <= '9';
+ }
+
+ private void skipDigits() {
+ while (pos < length) {
+ final int c = peek();
+ if (!isDigit(c)) {
+ break;
+ }
+ pos++;
+ }
}
- /**
- * Parse a property assignment from the token stream
- * @return the property assignment as a Node
- */
- private PropertyNode propertyAssignment() {
- // Capture firstToken.
- final long propertyToken = token;
- LiteralNode<?> name = null;
+ private Number parseNumber() {
+ final int start = pos;
+ int c = next();
+
+ if (c == '-') {
+ c = next();
+ }
+ if (!isDigit(c)) {
+ throw numberError(start);
+ }
+ // no more digits allowed after 0
+ if (c != '0') {
+ skipDigits();
+ }
- if (type == STRING) {
- name = getStringLiteral();
- } else if (type == ESCSTRING) {
- name = getLiteral();
+ // fraction
+ if (peek() == '.') {
+ pos++;
+ if (!isDigit(next())) {
+ throw numberError(pos - 1);
+ }
+ skipDigits();
+ }
+
+ // exponent
+ c = peek();
+ if (c == 'e' || c == 'E') {
+ pos++;
+ c = next();
+ if (c == '-' || c == '+') {
+ c = next();
+ }
+ if (!isDigit(c)) {
+ throw numberError(pos - 1);
+ }
+ skipDigits();
}
- if (name != null) {
- expect(COLON);
- final Expression value = jsonLiteral();
- return new PropertyNode(propertyToken, value.getFinish(), name, value, null, null);
+ final double d = Double.parseDouble(source.substring(start, pos));
+ if (JSType.isRepresentableAsInt(d)) {
+ return (int) d;
+ } else if (JSType.isRepresentableAsLong(d)) {
+ return (long) d;
+ }
+ return d;
+ }
+
+ private Object parseKeyword(final String keyword, final Object value) {
+ if (!source.regionMatches(pos, keyword, 0, keyword.length())) {
+ throw expectedError(pos, "json literal", "ident");
}
+ pos += keyword.length();
+ return value;
+ }
- // Raise an error.
- throw error(AbstractParser.message("expected", "string", type.getNameOrType()));
+ private int peek() {
+ if (pos >= length) {
+ return -1;
+ }
+ return source.charAt(pos);
+ }
+
+ private int next() {
+ final int next = peek();
+ pos++;
+ return next;
}
+ private void skipWhiteSpace() {
+ while (pos < length) {
+ switch (peek()) {
+ case '\t':
+ case '\r':
+ case '\n':
+ case ' ':
+ pos++;
+ break;
+ default:
+ return;
+ }
+ }
+ }
+
+ private static String toString(final int c) {
+ return c == EOF ? "eof" : String.valueOf((char) c);
+ }
+
+ ParserException error(final String message, final int start, final int length) throws ParserException {
+ final long token = Token.toDesc(STRING, start, length);
+ final int pos = Token.descPosition(token);
+ final Source src = Source.sourceFor("<json>", source);
+ final int lineNum = src.getLine(pos);
+ final int columnNum = src.getColumn(pos);
+ final String formatted = ErrorManager.format(message, src, lineNum, columnNum, token);
+ return new ParserException(JSErrorType.SYNTAX_ERROR, formatted, src, lineNum, columnNum, token);
+ }
+
+ private ParserException error(final String message, final int start) {
+ return error(message, start, length);
+ }
+
+ private ParserException numberError(final int start) {
+ return error(Lexer.message("json.invalid.number"), start);
+ }
+
+ private ParserException expectedError(final int start, final String expected, final String found) {
+ return error(AbstractParser.message("expected", expected, found), start);
+ }
+
+ private ParserException syntaxError(final int start, final String reason) {
+ final String message = ECMAErrors.getMessage("syntax.error.invalid.json", reason);
+ return error(message, start);
+ }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Lexer.java Mon Feb 09 09:52:48 2015 -0800
@@ -93,9 +93,6 @@
private static final String SPACETAB = " \t"; // ASCII space and tab
private static final String LFCR = "\n\r"; // line feed and carriage return (ctrl-m)
- private static final String JSON_WHITESPACE_EOL = LFCR;
- private static final String JSON_WHITESPACE = SPACETAB + LFCR;
-
private static final String JAVASCRIPT_WHITESPACE_EOL =
LFCR +
"\u2028" + // line separator
@@ -385,24 +382,6 @@
}
/**
- * Test whether a char is valid JSON whitespace
- * @param ch a char
- * @return true if valid JSON whitespace
- */
- public static boolean isJsonWhitespace(final char ch) {
- return JSON_WHITESPACE.indexOf(ch) != -1;
- }
-
- /**
- * Test whether a char is valid JSON end of line
- * @param ch a char
- * @return true if valid JSON end of line
- */
- public static boolean isJsonEOL(final char ch) {
- return JSON_WHITESPACE_EOL.indexOf(ch) != -1;
- }
-
- /**
* Test if char is a string delimiter, e.g. '\' or '"'. Also scans exec
* strings ('`') in scripting mode.
* @param ch a char
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Mon Feb 09 09:52:48 2015 -0800
@@ -60,6 +60,7 @@
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
@@ -904,7 +905,7 @@
* @throw SecurityException if not accessible
*/
private static void checkPackageAccess(final SecurityManager sm, final String fullName) {
- sm.getClass(); // null check
+ Objects.requireNonNull(sm);
final int index = fullName.lastIndexOf('.');
if (index != -1) {
final String pkgName = fullName.substring(0, index);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSONFunctions.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,19 +25,11 @@
package jdk.nashorn.internal.runtime;
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
import java.lang.invoke.MethodHandle;
import java.util.Iterator;
import java.util.concurrent.Callable;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.PropertyNode;
-import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.JSONParser;
-import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -78,20 +70,18 @@
* @return Object representation of JSON text given
*/
public static Object parse(final Object text, final Object reviver) {
- final String str = JSType.toString(text);
- final JSONParser parser = new JSONParser(sourceFor("<json>", str), new Context.ThrowErrorManager());
-
- Node node;
+ final String str = JSType.toString(text);
+ final Global global = Context.getGlobal();
+ final JSONParser parser = new JSONParser(str, global);
+ final Object value;
try {
- node = parser.parse();
+ value = parser.parse();
} catch (final ParserException e) {
throw ECMAErrors.syntaxError(e, "invalid.json", e.getMessage());
}
- final Global global = Context.getGlobal();
- final Object unfiltered = convertNode(global, node);
- return applyReviver(global, unfiltered, reviver);
+ return applyReviver(global, value, reviver);
}
// -- Internals only below this point
@@ -137,61 +127,6 @@
}
}
- // Converts IR node to runtime value
- private static Object convertNode(final Global global, final Node node) {
- if (node instanceof LiteralNode) {
- // check for array literal
- if (node.tokenType() == TokenType.ARRAY) {
- assert node instanceof LiteralNode.ArrayLiteralNode;
- final Node[] elements = ((LiteralNode.ArrayLiteralNode)node).getValue();
-
- // NOTE: We cannot use LiteralNode.isNumericArray() here as that
- // method uses symbols of element nodes. Since we don't do lower
- // pass, there won't be any symbols!
- if (isNumericArray(elements)) {
- final double[] values = new double[elements.length];
- int index = 0;
-
- for (final Node elem : elements) {
- values[index++] = JSType.toNumber(convertNode(global, elem));
- }
- return global.wrapAsObject(values);
- }
-
- final Object[] values = new Object[elements.length];
- int index = 0;
-
- for (final Node elem : elements) {
- values[index++] = convertNode(global, elem);
- }
-
- return global.wrapAsObject(values);
- }
-
- return ((LiteralNode<?>)node).getValue();
-
- } else if (node instanceof ObjectNode) {
- final ObjectNode objNode = (ObjectNode) node;
- final ScriptObject object = global.newObject();
-
- for (final PropertyNode pNode: objNode.getElements()) {
- final Node valueNode = pNode.getValue();
-
- final String name = pNode.getKeyName();
- final Object value = convertNode(global, valueNode);
- setPropertyValue(object, name, value);
- }
-
- return object;
- } else if (node instanceof UnaryNode) {
- // UnaryNode used only to represent negative number JSON value
- final UnaryNode unaryNode = (UnaryNode)node;
- return -((LiteralNode<?>)unaryNode.getExpression()).getNumber();
- } else {
- return null;
- }
- }
-
// add a new property if does not exist already, or else set old property
private static void setPropertyValue(final ScriptObject sobj, final String name, final Object value) {
final int index = ArrayIndex.getArrayIndex(name);
@@ -207,14 +142,4 @@
}
}
- // does the given IR node represent a numeric array?
- private static boolean isNumericArray(final Node[] values) {
- for (final Node node : values) {
- if (node instanceof LiteralNode && ((LiteralNode<?>)node).getValue() instanceof Number) {
- continue;
- }
- return false;
- }
- return true;
- }
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/PropertyMap.java Mon Feb 09 09:52:48 2015 -0800
@@ -486,7 +486,7 @@
*
* @return New {@link PropertyMap} with {@link Property} replaced.
*/
- PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
+ public PropertyMap replaceProperty(final Property oldProperty, final Property newProperty) {
if (listeners != null) {
listeners.propertyModified(oldProperty, newProperty);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptLoader.java Mon Feb 09 09:52:48 2015 -0800
@@ -26,6 +26,7 @@
package jdk.nashorn.internal.runtime;
import java.security.CodeSource;
+import java.util.Objects;
/**
* Responsible for loading script generated classes.
@@ -69,8 +70,7 @@
* @return Installed class.
*/
synchronized Class<?> installClass(final String name, final byte[] data, final CodeSource cs) {
- // null check
- cs.getClass();
+ Objects.requireNonNull(cs);
return defineClass(name, data, 0, data.length, cs);
}
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Mon Feb 09 09:52:48 2015 -0800
@@ -722,8 +722,12 @@
public void defineOwnProperty(final int index, final Object value) {
assert isValidArrayIndex(index) : "invalid array index";
final long longIndex = ArrayIndex.toLongIndex(index);
- doesNotHaveEnsureDelete(longIndex, getArray().length(), false);
- setArray(getArray().ensure(longIndex).set(index,value, false));
+ final long oldLength = getArray().length();
+ if (longIndex >= oldLength) {
+ setArray(getArray().ensure(longIndex));
+ doesNotHaveEnsureDelete(longIndex, oldLength, false);
+ }
+ setArray(getArray().set(index,value, false));
}
private void checkIntegerKey(final String key) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -118,7 +118,7 @@
return new SparseArrayData(this, safeIndex + 1);
}
//known to fit in int
- return toRealArrayData((int)safeIndex).ensure(safeIndex);
+ return toRealArrayData((int)safeIndex);
}
return this;
}
@@ -497,7 +497,9 @@
public abstract ArrayData shiftRight(final int by);
/**
- * Ensure that the given index exists and won't fail subsequent
+ * Ensure that the given index exists and won't fail in a subsequent access.
+ * If {@code safeIndex} is equal or greater than the current length the length is
+ * updated to {@code safeIndex + 1}.
*
* @param safeIndex the index to ensure wont go out of bounds
* @return new array data (or same)
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -57,7 +57,7 @@
}
/**
- * Check if we can put one more element at the end of this continous
+ * Check if we can put one more element at the end of this continuous
* array without reallocating, or if we are overwriting an already
* allocated element
*
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -221,7 +221,9 @@
final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength);
}
- setLength(safeIndex + 1);
+ if (safeIndex >= length()) {
+ setLength(safeIndex + 1);
+ }
return this;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -157,7 +157,9 @@
final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength);
}
- setLength(safeIndex + 1);
+ if (safeIndex >= length()) {
+ setLength(safeIndex + 1);
+ }
return this;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -139,7 +139,9 @@
final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed?
}
- setLength(safeIndex + 1);
+ if (safeIndex >= length()) {
+ setLength(safeIndex + 1);
+ }
return this;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -123,7 +123,9 @@
final int newLength = ArrayData.nextSize((int)safeIndex);
array = Arrays.copyOf(array, newLength); //fill with undefined or OK? TODO
}
- setLength(safeIndex + 1);
+ if (safeIndex >= length()) {
+ setLength(safeIndex + 1);
+ }
return this;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java Mon Feb 09 09:52:48 2015 -0800
@@ -135,10 +135,17 @@
@Override
public ArrayData ensure(final long safeIndex) {
+ // Usually #ensure only needs to be called if safeIndex is greater or equal current length.
+ // SparseArrayData is an exception as an index smaller than our current length may still
+ // exceed the underlying ArrayData's capacity. Because of this, SparseArrayData invokes
+ // its ensure method internally in various places where other ArrayData subclasses don't,
+ // making it safe for outside uses to only call ensure(safeIndex) if safeIndex >= length.
if (safeIndex < maxDenseLength && underlying.length() <= safeIndex) {
underlying = underlying.ensure(safeIndex);
}
- setLength(Math.max(safeIndex + 1, length()));
+ if (safeIndex >= length()) {
+ setLength(safeIndex + 1);
+ }
return this;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,6 +25,8 @@
package jdk.nashorn.internal.runtime.linker;
+import java.util.Objects;
+
/**
* Represents a an adapter for invoking superclass methods on an adapter instance generated by
* {@code JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
@@ -34,7 +36,7 @@
private final Object adapter;
JavaSuperAdapter(final Object adapter) {
- adapter.getClass(); // NPE check
+ Objects.requireNonNull(adapter);
this.adapter = adapter;
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/options/Options.java Mon Feb 09 09:52:48 2015 -0800
@@ -42,6 +42,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
+import java.util.Objects;
import java.util.PropertyPermission;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
@@ -143,7 +144,7 @@
* @return true if set to true, default value if unset or set to false
*/
public static boolean getBooleanProperty(final String name, final Boolean defValue) {
- name.getClass(); // null check
+ Objects.requireNonNull(name);
if (!name.startsWith("nashorn.")) {
throw new IllegalArgumentException(name);
}
@@ -184,7 +185,7 @@
* @return string property if set or default value
*/
public static String getStringProperty(final String name, final String defValue) {
- name.getClass(); // null check
+ Objects.requireNonNull(name);
if (! name.startsWith("nashorn.")) {
throw new IllegalArgumentException(name);
}
@@ -211,7 +212,7 @@
* @return integer property if set or default value
*/
public static int getIntProperty(final String name, final int defValue) {
- name.getClass(); // null check
+ Objects.requireNonNull(name);
if (! name.startsWith("nashorn.")) {
throw new IllegalArgumentException(name);
}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/JO.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/scripts/JO.java Mon Feb 09 09:52:48 2015 -0800
@@ -25,7 +25,6 @@
package jdk.nashorn.internal.scripts;
-import jdk.nashorn.internal.codegen.SpillObjectCreator;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
@@ -64,8 +63,9 @@
}
/**
- * Constructor that takes a pre-initialized spill pool. Used for
- * by {@link SpillObjectCreator} for intializing object literals
+ * Constructor that takes a pre-initialized spill pool. Used by
+ * {@link jdk.nashorn.internal.codegen.SpillObjectCreator} and
+ * {@link jdk.nashorn.internal.parser.JSONParser} for initializing object literals
*
* @param map property map
* @param primitiveSpill primitive spill pool
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/examples/json-parser-micro.js Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of Oracle nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function bench() {
+ var start = Date.now();
+ for (var i = 0; i < 2000; i++) {
+ JSON.parse(String(json));
+ }
+ print("1000 iterations in", Date.now() - start, "millis");
+}
+
+var json = '[\
+ {\
+ "_id": "54ca34171d3ade49782294c8",\
+ "index": 0,\
+ "guid": "ed0e74d5-ac63-47b6-8938-1750abab5770",\
+ "isActive": false,\
+ "balance": "$1,996.19",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 39,\
+ "eyeColor": "green",\
+ "name": "Rose Graham",\
+ "gender": "male",\
+ "company": "PRIMORDIA",\
+ "email": "rosegraham@primordia.com",\
+ "phone": "+1 (985) 600-3551",\
+ "address": "364 Melba Court, Succasunna, Texas, 8393",\
+ "about": "Sunt commodo cillum occaecat velit eu eiusmod ex eiusmod sunt deserunt nulla proident incididunt. Incididunt ullamco Lorem elit do culpa esse do ex dolor aliquip labore. Ullamco velit laboris incididunt dolor. Nostrud dolor sint pariatur fugiat ullamco exercitation. Eu laboris do cupidatat eiusmod incididunt mollit occaecat voluptate.",\
+ "registered": "2014-03-13T12:05:14 -01:00",\
+ "latitude": 18.55665,\
+ "longitude": 81.641001,\
+ "tags": [\
+ "sint",\
+ "Lorem",\
+ "veniam",\
+ "quis",\
+ "proident",\
+ "consectetur",\
+ "consequat"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Evangelina Morgan"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Saunders Snyder"\
+ },\
+ {\
+ "id": 2,\
+ "name": "Walker Wood"\
+ }\
+ ],\
+ "greeting": "Hello, Rose Graham! You have 1 unread messages.",\
+ "favoriteFruit": "strawberry"\
+ },\
+ {\
+ "_id": "54ca34176790c4c60fcae085",\
+ "index": 1,\
+ "guid": "9dc42e4c-b58f-4d92-a2ee-968d2b627d92",\
+ "isActive": true,\
+ "balance": "$3,832.97",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 40,\
+ "eyeColor": "brown",\
+ "name": "Delaney Cherry",\
+ "gender": "male",\
+ "company": "INJOY",\
+ "email": "delaneycherry@injoy.com",\
+ "phone": "+1 (807) 463-2295",\
+ "address": "470 Hale Avenue, Mulberry, District Of Columbia, 5455",\
+ "about": "Deserunt sit cupidatat elit Lorem excepteur ex. Magna officia minim cupidatat nulla enim deserunt. Amet ex in tempor commodo consequat non ad qui elit cupidatat esse labore sint.",\
+ "registered": "2014-03-27T23:06:33 -01:00",\
+ "latitude": -4.984238,\
+ "longitude": 116.039285,\
+ "tags": [\
+ "minim",\
+ "velit",\
+ "aute",\
+ "minim",\
+ "id",\
+ "enim",\
+ "enim"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Barrera Flowers"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Leann Larson"\
+ },\
+ {\
+ "id": 2,\
+ "name": "Latoya Petty"\
+ }\
+ ],\
+ "greeting": "Hello, Delaney Cherry! You have 2 unread messages.",\
+ "favoriteFruit": "strawberry"\
+ },\
+ {\
+ "_id": "54ca3417920666f00c54bfc4",\
+ "index": 2,\
+ "guid": "f91e08f8-1598-49bc-a08b-bb48f0cc1751",\
+ "isActive": true,\
+ "balance": "$2,932.84",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 28,\
+ "eyeColor": "brown",\
+ "name": "Mosley Hammond",\
+ "gender": "male",\
+ "company": "AQUACINE",\
+ "email": "mosleyhammond@aquacine.com",\
+ "phone": "+1 (836) 598-2591",\
+ "address": "879 Columbia Place, Seymour, Montana, 4897",\
+ "about": "Sunt laborum incididunt et elit in deserunt deserunt irure enim ea qui non. Minim nisi sint aute veniam reprehenderit veniam reprehenderit. Elit enim eu voluptate eu cupidatat nulla ea incididunt exercitation voluptate ut aliquip excepteur ipsum. Consequat anim fugiat irure Lorem anim consectetur est.",\
+ "registered": "2014-07-27T05:05:58 -02:00",\
+ "latitude": -43.608015,\
+ "longitude": -38.33894,\
+ "tags": [\
+ "proident",\
+ "incididunt",\
+ "eiusmod",\
+ "anim",\
+ "consectetur",\
+ "qui",\
+ "excepteur"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Hanson Davidson"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Autumn Kaufman"\
+ },\
+ {\
+ "id": 2,\
+ "name": "Tammy Foley"\
+ }\
+ ],\
+ "greeting": "Hello, Mosley Hammond! You have 4 unread messages.",\
+ "favoriteFruit": "apple"\
+ },\
+ {\
+ "_id": "54ca341753b67572a2b04935",\
+ "index": 3,\
+ "guid": "3377416b-43a2-4f9e-ada3-2479e13b44b8",\
+ "isActive": false,\
+ "balance": "$3,821.54",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 31,\
+ "eyeColor": "green",\
+ "name": "Mueller Barrett",\
+ "gender": "male",\
+ "company": "GROK",\
+ "email": "muellerbarrett@grok.com",\
+ "phone": "+1 (890) 535-2834",\
+ "address": "571 Norwood Avenue, Westwood, Arkansas, 2164",\
+ "about": "Occaecat est sunt commodo ut ex excepteur elit nulla velit minim commodo commodo esse. Lorem quis eu minim consectetur. Cupidatat cupidatat consequat sit eu ex non quis nulla veniam sint enim excepteur. Consequat minim duis do do minim fugiat minim elit laborum ut velit. Occaecat laboris veniam sint reprehenderit.",\
+ "registered": "2014-07-18T17:15:35 -02:00",\
+ "latitude": 10.746577,\
+ "longitude": -160.266041,\
+ "tags": [\
+ "reprehenderit",\
+ "veniam",\
+ "sint",\
+ "commodo",\
+ "exercitation",\
+ "cillum",\
+ "sunt"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Summers Finch"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Tracie Mcdaniel"\
+ },\
+ {\
+ "id": 2,\
+ "name": "Ayers Patrick"\
+ }\
+ ],\
+ "greeting": "Hello, Mueller Barrett! You have 7 unread messages.",\
+ "favoriteFruit": "apple"\
+ },\
+ {\
+ "_id": "54ca34172775ab9615db0d1d",\
+ "index": 4,\
+ "guid": "a3102a3e-3f08-4df3-b5b5-62eff985d5ca",\
+ "isActive": true,\
+ "balance": "$3,962.27",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 34,\
+ "eyeColor": "green",\
+ "name": "Patrick Foster",\
+ "gender": "male",\
+ "company": "QUAREX",\
+ "email": "patrickfoster@quarex.com",\
+ "phone": "+1 (805) 577-2362",\
+ "address": "640 Richards Street, Roberts, American Samoa, 5530",\
+ "about": "Aute occaecat occaecat ad eiusmod esse aliqua ullamco minim. Exercitation aute ut ex nostrud deserunt laboris officia amet enim do. Cillum officia laborum occaecat eiusmod reprehenderit ex et aliqua minim elit ex aliqua mollit. Occaecat dolor in fugiat laboris aliquip nisi ad voluptate duis eiusmod ad do.",\
+ "registered": "2014-07-22T16:45:35 -02:00",\
+ "latitude": 6.609025,\
+ "longitude": -5.357026,\
+ "tags": [\
+ "ea",\
+ "ut",\
+ "excepteur",\
+ "enim",\
+ "ad",\
+ "non",\
+ "sit"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Duncan Lewis"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Alyce Benton"\
+ },\
+ {\
+ "id": 2,\
+ "name": "Angelique Larsen"\
+ }\
+ ],\
+ "greeting": "Hello, Patrick Foster! You have 1 unread messages.",\
+ "favoriteFruit": "strawberry"\
+ },\
+ {\
+ "_id": "54ca3417a190f26fef815f6d",\
+ "index": 5,\
+ "guid": "c09663dd-bb0e-45a4-960c-232c0e8a9486",\
+ "isActive": false,\
+ "balance": "$1,871.12",\
+ "picture": "http://placehold.it/32x32",\
+ "age": 20,\
+ "eyeColor": "blue",\
+ "name": "Foreman Chaney",\
+ "gender": "male",\
+ "company": "DEMINIMUM",\
+ "email": "foremanchaney@deminimum.com",\
+ "phone": "+1 (966) 523-2182",\
+ "address": "960 Granite Street, Sunnyside, Tennessee, 1097",\
+ "about": "Adipisicing nisi qui id sit incididunt aute exercitation veniam consequat ipsum sit irure. Aute officia commodo Lorem consequat. Labore exercitation consequat voluptate deserunt consequat do est fugiat nisi eu dolor minim id ea.",\
+ "registered": "2015-01-21T00:18:00 -01:00",\
+ "latitude": -69.841726,\
+ "longitude": 121.809383,\
+ "tags": [\
+ "laboris",\
+ "sunt",\
+ "exercitation",\
+ "enim",\
+ "anim",\
+ "excepteur",\
+ "tempor"\
+ ],\
+ "friends": [\
+ {\
+ "id": 0,\
+ "name": "Espinoza Johnston"\
+ },\
+ {\
+ "id": 1,\
+ "name": "Doreen Holder"\
+ },\
+ {\
+ "id": 2,\
+ "name": "William Ellison"\
+ }\
+ ],\
+ "greeting": "Hello, Foreman Chaney! You have 5 unread messages.",\
+ "favoriteFruit": "strawberry"\
+ }\
+]';
+
+for (var i = 0; i < 100; i++) {
+ bench();
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062141.js Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8062141: Various performance issues parsing JSON
+ *
+ * @test
+ * @run
+ */
+
+function testJson(json) {
+ try {
+ print(JSON.stringify(JSON.parse(json)));
+ } catch (error) {
+ print(error);
+ }
+}
+
+testJson('"\\u003f"');
+testJson('"\\u0"');
+testJson('"\\u0"');
+testJson('"\\u00"');
+testJson('"\\u003"');
+testJson('"\\u003x"');
+testJson('"\\"');
+testJson('"');
+testJson('+1');
+testJson('-1');
+testJson('1.');
+testJson('.1');
+testJson('01');
+testJson('1e');
+testJson('1e0');
+testJson('1a');
+testJson('1e+');
+testJson('1e-');
+testJson('0.0e+0');
+testJson('0.0e-0');
+testJson('[]');
+testJson('[ 1 ]');
+testJson('[1,]');
+testJson('[ 1 , 2 ]');
+testJson('[1, 2');
+testJson('{}');
+testJson('{ "a" : "b" }');
+testJson('{ "a" : "b" ');
+testJson('{ "a" : }');
+testJson('true');
+testJson('tru');
+testJson('true1');
+testJson('false');
+testJson('fals');
+testJson('falser');
+testJson('null');
+testJson('nul');
+testJson('null0');
+testJson('{} 0');
+testJson('{} a');
+testJson('[] 0');
+testJson('[] a');
+testJson('1 0');
+testJson('1 a');
+testJson('["a":true]');
+testJson('{"a",truer}');
+testJson('{"a":truer}');
+testJson('[1, 2, 3]');
+testJson('[9223372036854774000, 9223372036854775000, 9223372036854776000]');
+testJson('[1.1, 1.2, 1.3]');
+testJson('[1, 1.2, 9223372036854776000, null, true]');
+testJson('{ "a" : "string" , "b": 1 , "c" : 1.2 , "d" : 9223372036854776000 , "e" : null , "f" : true }');
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8062141.js.EXPECTED Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,120 @@
+"?"
+SyntaxError: Invalid JSON: <json>:1:4 Invalid hex digit
+"\u0"
+ ^
+SyntaxError: Invalid JSON: <json>:1:4 Invalid hex digit
+"\u0"
+ ^
+SyntaxError: Invalid JSON: <json>:1:5 Invalid hex digit
+"\u00"
+ ^
+SyntaxError: Invalid JSON: <json>:1:6 Invalid hex digit
+"\u003"
+ ^
+SyntaxError: Invalid JSON: <json>:1:6 Invalid hex digit
+"\u003x"
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Missing close quote
+"\"
+ ^
+SyntaxError: Invalid JSON: <json>:1:1 Missing close quote
+"
+ ^
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found +
++1
+^
+-1
+SyntaxError: Invalid JSON: <json>:1:2 Invalid JSON number format
+1.
+ ^
+SyntaxError: Invalid JSON: <json>:1:0 Invalid JSON number format
+.1
+^
+SyntaxError: Invalid JSON: <json>:1:1 Expected eof but found 1
+01
+ ^
+SyntaxError: Invalid JSON: <json>:1:2 Invalid JSON number format
+1e
+ ^
+1
+SyntaxError: Invalid JSON: <json>:1:1 Expected eof but found a
+1a
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Invalid JSON number format
+1e+
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Invalid JSON number format
+1e-
+ ^
+0
+0
+[]
+[1]
+SyntaxError: Invalid JSON: <json>:1:3 Trailing comma is not allowed in JSON
+[1,]
+ ^
+[1,2]
+SyntaxError: Invalid JSON: <json>:1:5 Expected , or ] but found eof
+[1, 2
+ ^
+{}
+{"a":"b"}
+SyntaxError: Invalid JSON: <json>:1:12 Expected , or } but found eof
+{ "a" : "b"
+ ^
+SyntaxError: Invalid JSON: <json>:1:8 Expected json literal but found }
+{ "a" : }
+ ^
+true
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+tru
+^
+SyntaxError: Invalid JSON: <json>:1:4 Expected eof but found 1
+true1
+ ^
+false
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+fals
+^
+SyntaxError: Invalid JSON: <json>:1:5 Expected eof but found r
+falser
+ ^
+null
+SyntaxError: Invalid JSON: <json>:1:0 Expected json literal but found ident
+nul
+^
+SyntaxError: Invalid JSON: <json>:1:4 Expected eof but found 0
+null0
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found 0
+{} 0
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found a
+{} a
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found 0
+[] 0
+ ^
+SyntaxError: Invalid JSON: <json>:1:3 Expected eof but found a
+[] a
+ ^
+SyntaxError: Invalid JSON: <json>:1:2 Expected eof but found 0
+1 0
+ ^
+SyntaxError: Invalid JSON: <json>:1:2 Expected eof but found a
+1 a
+ ^
+SyntaxError: Invalid JSON: <json>:1:4 Expected , or ] but found :
+["a":true]
+ ^
+SyntaxError: Invalid JSON: <json>:1:4 Expected : but found ,
+{"a",truer}
+ ^
+SyntaxError: Invalid JSON: <json>:1:9 Expected , or } but found r
+{"a":truer}
+ ^
+[1,2,3]
+[9223372036854773800,9223372036854774800,9223372036854776000]
+[1.1,1.2,1.3]
+[1,1.2,9223372036854776000,null,true]
+{"a":"string","b":1,"c":1.2,"d":9223372036854776000,"e":null,"f":true}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8067139.js Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8067139: Finally blocks inlined incorrectly
+ *
+ * @test
+ * @run
+ */
+
+// Test case for JDK-8067139
+// as well as for JDK-8030198 which is a duplicate.
+(function(){
+ var catchCount = 0;
+ try {
+ (function (){
+ try {
+ return;
+ } catch(x) {
+ ++catchCount;
+ } finally {
+ throw 0;
+ }
+ })();
+ Assert.fail(); // must throw
+ } catch(e) {
+ Assert.assertEquals(e, 0); // threw 0
+ Assert.assertEquals(catchCount, 0); // inner catch never executed
+ }
+})();
+
+// Test case for JDK-8048862 which is a duplicate of this bug
+var ret = (function(o) {
+ try{
+ with(o) {
+ return x;
+ }
+ } finally {
+ try {
+ return x;
+ } catch(e) {
+ Assert.assertTrue(e instanceof ReferenceError);
+ return 2;
+ }
+ }
+})({x: 1});
+Assert.assertEquals(ret, 2); // executed the catch block
+
+// Test cases for JDK-8066231 that is a duplicate of this bug
+// Case 1
+(function (){ try { Object; } catch(x if x >>>=0) { throw x2; } finally { } })();
+// Case 2
+try {
+ (function (){ try { return; } catch(x) { return x ^= 0; } finally { throw 0; } })();
+ Assert.fail();
+} catch(e) {
+ Assert.assertEquals(e, 0); // threw 0
+}
+// Case 3
+try {
+ (function (){ try { return; } catch(x) { return x ^= Object; } finally { throw Object; } })();
+ Assert.fail();
+} catch(e) {
+ Assert.assertEquals(e, Object); // threw Object
+}
+// Case from comment
+try {
+ (function () { try { Object } catch(x) { (x=y); return; } finally { throw Object; } })();
+ Assert.fail();
+} catch(e) {
+ Assert.assertEquals(e, Object); // threw Object
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068872.js Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8068872: Nashorn JSON.parse drops numeric keys
+ *
+ * @test
+ * @run
+ */
+
+print(JSON.stringify(JSON.parse('{"3": 1, "5": "a"}')));
+print(JSON.stringify(JSON.parse('{"5": 1, "3": "a"}')));
+print(JSON.stringify(JSON.parse('{"0": 1, "4294967294": "a"}')));
+print(JSON.stringify(JSON.parse('{"4294967294": 1, "0": "a"}')));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8068872.js.EXPECTED Mon Feb 09 09:52:48 2015 -0800
@@ -0,0 +1,4 @@
+{"3":1,"5":"a"}
+{"3":"a","5":1}
+{"0":1,"4294967294":"a"}
+{"0":"a","4294967294":1}
--- a/nashorn/test/script/basic/NASHORN-623.js.EXPECTED Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/test/script/basic/NASHORN-623.js.EXPECTED Mon Feb 09 09:52:48 2015 -0800
@@ -1,3 +1,3 @@
-SyntaxError: Invalid JSON: <json>:1:12 Expected number but found ident
+SyntaxError: Invalid JSON: <json>:1:11 Invalid JSON number format
{ "test" : -xxx }
- ^
+ ^
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Fri Feb 06 19:49:20 2015 +0300
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Mon Feb 09 09:52:48 2015 -0800
@@ -721,6 +721,15 @@
assertTrue(invoked.get());
}
+ @Test
+ public void testLengthOnArrayLikeObjects() throws Exception {
+ final ScriptEngine e = new ScriptEngineManager().getEngineByName("nashorn");
+ final Object val = e.eval("var arr = { length: 1, 0: 1}; arr.length");
+
+ assertTrue(Number.class.isAssignableFrom(val.getClass()));
+ assertTrue(((Number)val).intValue() == 1);
+ }
+
// @bug JDK-8068603: NashornScriptEngine.put/get() impls don't conform to NPE, IAE spec assertions
@Test
public void illegalBindingsValuesTest() throws Exception {
--- a/test/make/TestJavaCompilation.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/test/make/TestJavaCompilation.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -50,6 +50,9 @@
clean-jar1:
$(RM) -r $(OUTPUT_DIR)/_jar1* $(OUTPUT_DIR)/jar1*
+$(JAR1_MANIFEST): | $(OUTPUT_DIR)/_jar1_created
+ $(ECHO) "Test-Attribute: value" > $(JAR1_MANIFEST)
+
$(OUTPUT_DIR)/_jar1_created: $(DEPS)
$(RM) -r $(JAR1_SRC_ROOT)
$(RM) $(JAR1_FILE)
@@ -61,7 +64,6 @@
$(TOUCH) $(JAR1_SRC_ROOT)/dir1/file1.class
$(TOUCH) $(JAR1_SRC_ROOT)/dir2/file2.class
$(TOUCH) $(JAR1_SRC_ROOT)/META-INF/metafile
- $(ECHO) "Test-Attribute: value" > $(JAR1_MANIFEST)
$(TOUCH) $@
$(eval $(call SetupArchive,BUILD_JAR1, \
@@ -77,7 +79,7 @@
$(DIFF) -r $(JAR1_SRC_ROOT)/dir1 $(JAR1_UNZIP)/dir1
$(DIFF) -r $(JAR1_SRC_ROOT)/dir2 $(JAR1_UNZIP)/dir2
$(DIFF) -r $(JAR1_SRC_ROOT)/META-INF/metafile $(JAR1_UNZIP)/META-INF/metafile
- if [ "`$(GREP) 'Test-Attribute: value' $(JAR1_MANIFEST)`" = "" ]; then \
+ if [ "`$(GREP) 'Test-Attribute: value' $(JAR1_UNZIP)/META-INF/MANIFEST.MF`" = "" ]; then \
$(ECHO) "Could not find Test-Attribute in manifest of $(JAR1_FILE)"; \
exit 1; \
fi
@@ -88,7 +90,7 @@
# Change a source file and call this makefile again to force the jar to be
# updated.
-$(OUTPUT_DIR)_jar1_updated: $(OUTPUT_DIR)/_jar1_verified
+$(OUTPUT_DIR)/_jar1_updated: $(OUTPUT_DIR)/_jar1_verified
$(ECHO) updated > $(JAR1_SRC_ROOT)/dir1/file1.class
$(ECHO) updated > $(JAR1_SRC_ROOT)/META-INF/metafile
$(TOUCH) $(OUTPUT_DIR)/_jar1_created
@@ -96,9 +98,26 @@
$(TOUCH) $@
update-jar1: $(OUTPUT_DIR)_jar1_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar1_updated
-.PHONY: clean-jar1 create-jar1 update-jar1
+# Change the manifest file and call this makefile again to force the jar
+# to be updated
+$(OUTPUT_DIR)/_jar1_updated_manifest: $(OUTPUT_DIR)/_jar1_updated
+ $(ECHO) "Test-Attribute: foobar" > $(JAR1_MANIFEST)
+ +$(MAKE) -f $(THIS_FILE) $(BUILD_JAR1)
+ $(RM) -r $(JAR1_UNZIP)
+ $(MKDIR) -p $(JAR1_UNZIP)
+ $(CD) $(JAR1_UNZIP) && $(UNZIP) $(JAR1_FILE) $(LOG_DEBUG)
+ if [ "`$(GREP) 'Test-Attribute: foobar' $(JAR1_UNZIP)/META-INF/MANIFEST.MF`" = "" ]; then \
+ $(ECHO) "Could not find Test-Attribute in manifest of $(JAR1_FILE)"; \
+ exit 1; \
+ fi
+ $(TOUCH) $@
+
+update-jar1-manifest: $(OUTPUT_DIR)/_jar1_updated_manifest
+
+TEST_TARGETS += $(OUTPUT_DIR)/_jar1_updated $(OUTPUT_DIR)/_jar1_updated_manifest
+
+.PHONY: clean-jar1 create-jar1 update-jar1 update-jar1-manifest
################################################################################
# Test: jar2
@@ -139,14 +158,14 @@
create-jar2: $(OUTPUT_DIR)/_jar2_verified
TEST_TARGETS += $(OUTPUT_DIR)/_jar2_verified
-$(OUTPUT_DIR)_jar2_updated: $(OUTPUT_DIR)/_jar2_verified
+$(OUTPUT_DIR)/_jar2_updated: $(OUTPUT_DIR)/_jar2_verified
$(ECHO) updated > $(JAR2_SRC_ROOT1)/dir1/file1.class
$(TOUCH) $(OUTPUT_DIR)/_jar2_created
+$(MAKE) -f $(THIS_FILE) $(OUTPUT_DIR)/_jar2_verified
$(TOUCH) $@
-update-jar2: $(OUTPUT_DIR)_jar2_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar2_updated
+update-jar2: $(OUTPUT_DIR)/_jar2_updated
+TEST_TARGETS += $(OUTPUT_DIR)/_jar2_updated
.PHONY: clean-jar2 create-jar2 update-jar2
@@ -200,14 +219,14 @@
create-jar3: $(OUTPUT_DIR)/_jar3_verified
TEST_TARGETS += $(OUTPUT_DIR)/_jar3_verified
-$(OUTPUT_DIR)_jar3_updated: $(OUTPUT_DIR)/_jar3_verified
+$(OUTPUT_DIR)/_jar3_updated: $(OUTPUT_DIR)/_jar3_verified
$(ECHO) updated > $(JAR3_SRC_ROOT2)/extra-file
$(TOUCH) $(OUTPUT_DIR)/_jar3_created
+$(MAKE) -f $(THIS_FILE) $(OUTPUT_DIR)/_jar3_verified
$(TOUCH) $@
-update-jar3: $(OUTPUT_DIR)_jar3_updated
-TEST_TARGETS += $(OUTPUT_DIR)_jar3_updated
+update-jar3: $(OUTPUT_DIR)/_jar3_updated
+TEST_TARGETS += $(OUTPUT_DIR)/_jar3_updated
.PHONY: clean-jar3 create-jar3 update-jar3
--- a/test/make/TestMakeBase.gmk Fri Feb 06 19:49:20 2015 +0300
+++ b/test/make/TestMakeBase.gmk Mon Feb 09 09:52:48 2015 -0800
@@ -33,7 +33,14 @@
$(SRC_ROOT)/make/common/MakeBase.gmk \
#
+# On macosx, file system timestamps only have 1 second resultion so must add
+# sleeps to properly test dependencies.
+ifeq ($(OPENJDK_BUILD_OS), macosx)
+ SLEEP_ON_MAC := sleep 1
+endif
+
OUTPUT_DIR := $(TESTMAKE_OUTPUTDIR)/make-base
+$(call MakeDir, $(OUTPUT_DIR))
################################################################################
# Escape $
@@ -56,5 +63,124 @@
TEST_TARGETS += $(ESCAPE_DOLLAR_DIR)/_escape_dollar
################################################################################
+# Test Equals
+
+EQUALS_VALUE1 := value1$(SPACE)
+EQUALS_VALUE2 := value2
+
+ifneq ($(call equals, $(EQUALS_VALUE1), $(EQUALS_VALUE2)), )
+ $(error The strings >$(EQUALS_VALUE1)< and >$(EQUALS_VALUE2)< are equal)
+endif
+
+ifeq ($(call equals, $(EQUALS_VALUE1), $(EQUALS_VALUE1)), )
+ $(error The strings >$(EQUALS_VALUE1)< and >$(EQUALS_VALUE1)< are not equal)
+endif
+
+################################################################################
+# Test ShellQuote
+
+SHELL_QUOTE_VALUE := foo '""' "''" bar
+SHELL_QUOTE_RESULT := $(shell $(ECHO) $(call ShellQuote, \
+ $(SHELL_QUOTE_VALUE)))
+
+ifneq ($(SHELL_QUOTE_VALUE), $(SHELL_QUOTE_RESULT))
+ $(error Expected: >$(SHELL_QUOTE_VALUE)< - Result: >$(SHELL_QUOTE_RESULT)<)
+endif
+
+################################################################################
+# Test read and write to file
+
+READ_WRITE_FILE := $(OUTPUT_DIR)/read-write
+READ_WRITE_VALUE := foo '""' "''" \t\n\\ bar
+$(call WriteFile, $(READ_WRITE_VALUE), $(READ_WRITE_FILE))
+READ_WRITE_RESULT := $(call ReadFile, $(READ_WRITE_FILE))
+
+ifneq ($(READ_WRITE_VALUE), $(READ_WRITE_RESULT))
+ $(error Expected: >$(READ_WRITE_VALUE)< - Result: >$(READ_WRITE_RESULT)<)
+endif
+
+################################################################################
+# Test creating dependencies on make variables
+
+VARDEP_DIR := $(OUTPUT_DIR)/vardep
+VARDEP_SRC_FILE := $(VARDEP_DIR)/src-file
+VARDEP_TARGET_FILE := $(VARDEP_DIR)/target-file
+VARDEP_FLAG_FILE := $(VARDEP_DIR)/flag-file
+
+$(VARDEP_DIR)/src-file:
+ $(MKDIR) -p $(@D)
+ $(ECHO) "some string XXX" > $@
+
+$(VARDEP_TARGET_FILE): $(VARDEP_DIR)/src-file \
+ $(call DependOnVariable, VARDEP_TEST_VAR)
+ $(MKDIR) -p $(@D)
+ $(SED) -e 's/XXX/$(VARDEP_TEST_VAR)/g' $< > $@
+ $(TOUCH) $(VARDEP_FLAG_FILE)
+
+test-vardep:
+ $(RM) $(VARDEP_SRC_FILE) $(VARDEP_TARGET_FILE) $(VARDEP_FLAG_FILE)
+ #
+ # Simply create the target file and verify that it has the correct value
+ #
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value1 $(VARDEP_TARGET_FILE)
+ $(PRINTF) "Expecting value1: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test "some string value1" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test -e $(VARDEP_FLAG_FILE)
+ #
+ # Make the target file again and verify that the value is updated with
+ # the new value
+ #
+ $(SLEEP_ON_MAC)
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value2 $(VARDEP_TARGET_FILE)
+ $(PRINTF) "Expecting value2: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test "some string value2" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test -e $(VARDEP_FLAG_FILE)
+ #
+ # Make the target again with the same value and verify that the recipe
+ # was never run by checking that the flag file was not recreated
+ #
+ $(SLEEP_ON_MAC)
+ $(RM) $(VARDEP_FLAG_FILE)
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=value2 $(VARDEP_TARGET_FILE)
+ $(PRINTF) "Expecting value2: %s\n" "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test "some string value2" = "`$(CAT) $(VARDEP_DIR)/target-file`"
+ test ! -e $(VARDEP_FLAG_FILE)
+ #
+ # Test running with spaces at the end and the middle of the value
+ # and verify that the file isn't rewritten the second time
+ #
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR="value3 foo " $(VARDEP_TARGET_FILE)
+ $(RM) $(VARDEP_FLAG_FILE)
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR="value3 foo" $(VARDEP_TARGET_FILE)
+ test ! -e $(VARDEP_FLAG_FILE)
+ $(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR=" value3 foo" $(VARDEP_TARGET_FILE)
+ test ! -e $(VARDEP_FLAG_FILE)
+
+# Test specifying a specific value file to store variable in
+VARDEP_VALUE_FILE := $(VARDEP_DIR)/value-file
+VARDEP_TEST_VAR2 := value3
+
+VARDEP_RETURN_VALUE := $(call DependOnVariable, VARDEP_TEST_VAR2, $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_VALUE_FILE), $(VARDEP_RETURN_VALUE))
+ $(error Expected: $(VARDEP_VALUE_FILE) - DependOnVariable: $(VARDEP_RETURN_VALUE))
+endif
+VARDEP_FILE_CONTENTS := $(shell $(CAT) $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_TEST_VAR2), $(VARDEP_FILE_CONTENTS))
+ $(error Expected: $(VARDEP_TEST_VAR2) - DependOnVariable file contained: \
+ $(VARDEP_FILE_CONTENTS))
+endif
+
+# Test with a variable value containing some problematic characters
+VARDEP_TEST_VAR3 := foo '""' "''" bar
+VARDEP_VALUE_FILE := $(call DependOnVariable, VARDEP_TEST_VAR3)
+VARDEP_FILE_CONTENTS := $(shell $(CAT) $(VARDEP_VALUE_FILE))
+ifneq ($(VARDEP_TEST_VAR3), $(VARDEP_FILE_CONTENTS))
+ $(error Expected: >$(VARDEP_TEST_VAR3)< - DependOnVariable file contained: \
+ >$(VARDEP_FILE_CONTENTS)<)
+endif
+
+TEST_TARGETS += test-vardep
+
+################################################################################
all: $(TEST_TARGETS)