diff --git a/.hgtags b/.hgtags
index 8ad989563ae..f496bfd1d5d 100644
--- a/.hgtags
+++ b/.hgtags
@@ -290,3 +290,4 @@ abbfccd659b91a7bb815d5e36fed635dcdd40f31 jdk9-b44
bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45
722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46
8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47
+b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index e95f2721df1..26c2321b403 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -290,3 +290,4 @@ f7c11da0b0481d49cc7a65a453336c108191e821 jdk9-b42
3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45
12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46
b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47
+0064e246d83f6f9fc245c19b6d05041ecaf4b6d4 jdk9-b48
diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4
index 62d83574289..800c52b844b 100644
--- a/common/autoconf/basics.m4
+++ b/common/autoconf/basics.m4
@@ -987,3 +987,26 @@ AC_DEFUN_ONCE([BASIC_TEST_USABILITY_ISSUES],
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)
+])
diff --git a/common/autoconf/bootcycle-spec.gmk.in b/common/autoconf/bootcycle-spec.gmk.in
index a547f34c951..6e68c3a0b34 100644
--- a/common/autoconf/bootcycle-spec.gmk.in
+++ b/common/autoconf/bootcycle-spec.gmk.in
@@ -46,8 +46,12 @@ endif
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
diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac
index 146556f479e..902ba475684 100644
--- a/common/autoconf/configure.ac
+++ b/common/autoconf/configure.ac
@@ -113,6 +113,7 @@ HELP_SETUP_DEPENDENCY_HELP
# 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
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 21ab1f47ecd..11b5d337733 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -853,6 +853,7 @@ OS_VERSION_MICRO
OS_VERSION_MINOR
OS_VERSION_MAJOR
PKG_CONFIG
+BASH_ARGS
CODESIGN
XATTR
DSYMUTIL
@@ -3522,6 +3523,9 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+# 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 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++"
#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 @@ $as_echo "yes" >&6; }
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 @@ $as_echo "$as_me: Trying to extract Visual Studio environment variables" >&6;}
# 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
diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in
index 1c6c1c40132..d25b35b2070 100644
--- a/common/autoconf/spec.gmk.in
+++ b/common/autoconf/spec.gmk.in
@@ -78,6 +78,11 @@ endif
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 @@ MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/makesupport
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 @@ endif
# 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.
diff --git a/corba/.hgtags b/corba/.hgtags
index a6362dd4bef..5fa0c422fef 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -290,3 +290,4 @@ e27c725d6c9d155667b35255f442d4ceb8c3c084 jdk9-b40
9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45
326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46
ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47
+a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 5d7b668b46c..a0e96eab962 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -450,3 +450,4 @@ c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45
a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46
3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47
+cc775a4a24c7f5d9e624b4205e9fbd48a17331f6 jdk9-b48
diff --git a/hotspot/make/aix/makefiles/xlc.make b/hotspot/make/aix/makefiles/xlc.make
index b6525327528..17a71b60124 100644
--- a/hotspot/make/aix/makefiles/xlc.make
+++ b/hotspot/make/aix/makefiles/xlc.make
@@ -74,6 +74,12 @@ CFLAGS += -D_REENTRANT
# 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)
diff --git a/hotspot/make/linux/makefiles/build_vm_def.sh b/hotspot/make/linux/makefiles/build_vm_def.sh
deleted file mode 100644
index ea81ff6c22f..00000000000
--- a/hotspot/make/linux/makefiles/build_vm_def.sh
+++ /dev/null
@@ -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
diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make
index 65b11f544d0..d0c31ca125c 100644
--- a/hotspot/make/linux/makefiles/vm.make
+++ b/hotspot/make/linux/makefiles/vm.make
@@ -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 @@ mapfile_reorder : mapfile $(REORDERFILE)
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 $@
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index dfc67d5df66..739cc9612bd 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -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 Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
%}
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);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index 24587840f98..2cb6bd820d0 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -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 @@ void MacroAssembler::string_indexofC8(Register str1, Register str2,
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 @@ void MacroAssembler::string_indexof(Register str1, Register str2,
//
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 @@ void MacroAssembler::string_compare(Register str1, Register str2,
// 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 @@ void MacroAssembler::string_compare(Register str1, Register str2,
// 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)
diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
index b509cf94110..c9dd76b7881 100644
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp
+++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp
@@ -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 @@ static pid_t filename_to_pid(const char* filename) {
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 @@ static bool is_directory_secure(const char* path) {
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;
}
- 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;
+
+ // 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;
+ }
+}
+
+// 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
-//
-// the caller is expected to free the allocated memory.
+// Return the user name for the given user id.
//
+// 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 @@ static char* get_user_name_slow(int vmid, TRAPS) {
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 @@ static void remove_file(const char* path) {
}
}
-
-// 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 @@ static void remove_file(const char* dirname, const char* filename) {
// 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 @@ static void cleanup_sharedmem_resources(const char* dirname) {
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 @@ static int create_sharedmem_resources(const char* dirname, const char* filename,
return -1;
}
- int result;
-
- RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result);
- if (result == OS_ERR) {
- if (PrintMiscellaneous && Verbose) {
- warning("could not create file %s: %s\n", filename, strerror(errno));
- }
+ 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;
+
+ // 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) {
+ 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 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
// 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 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) {
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 @@ static char* mmap_create_shared(size_t size) {
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 @@ static char* mmap_create_shared(size_t size) {
// 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 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
char* mapAddress;
int result;
int fd;
- size_t size;
+ size_t size = 0;
const char* luser = NULL;
int mmap_prot;
@@ -819,12 +1124,18 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// 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 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
// 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 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor
"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;
diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp
index 5a546f50b4f..1d43669209e 100644
--- a/hotspot/src/share/vm/code/codeCache.cpp
+++ b/hotspot/src/share/vm/code/codeCache.cpp
@@ -199,15 +199,10 @@ void CodeCache::initialize_heaps() {
}
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,18 +211,27 @@ void CodeCache::initialize_heaps() {
// 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) {
@@ -284,7 +288,7 @@ const char* CodeCache::get_code_heap_flag_name(int code_blob_type) {
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 @@ void CodeCache::add_heap(ReservedSpace rs, const char* name, size_t size_initial
_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 @@ void CodeCache::initialize() {
} 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
diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp
index 287c531a4de..d682f90c5b2 100644
--- a/hotspot/src/share/vm/code/codeCache.hpp
+++ b/hotspot/src/share/vm/code/codeCache.hpp
@@ -98,12 +98,13 @@ class CodeCache : AllStatic {
// 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
diff --git a/hotspot/src/share/vm/compiler/compilerOracle.cpp b/hotspot/src/share/vm/compiler/compilerOracle.cpp
index a6351be1783..8299da22f0f 100644
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp
@@ -553,7 +553,8 @@ static MethodMatcher::Mode check_mode(char name[], const char*& error_msg) {
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 @@ static MethodMatcher* scan_flag_and_value(const char* type, const char* line, in
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 @@ void CompilerOracle::parse_from_line(char* line) {
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 @@ void CompilerOracle::parse_from_line(char* line) {
//
// 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 @@ void CompilerOracle::parse_from_line(char* line) {
// 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);
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index 7c9da72c68e..45eeb9672ff 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -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* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
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 @@ bool LibraryCallKit::inline_string_indexOf() {
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 @@ bool LibraryCallKit::inline_string_indexOf() {
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);
diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp
index 6284abde6e2..b0bdb3c16da 100644
--- a/hotspot/src/share/vm/opto/output.cpp
+++ b/hotspot/src/share/vm/opto/output.cpp
@@ -2475,7 +2475,7 @@ void Scheduling::DoScheduling() {
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...
}
diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp
index d6ac1020266..2aba90329f2 100644
--- a/hotspot/src/share/vm/opto/postaloc.cpp
+++ b/hotspot/src/share/vm/opto/postaloc.cpp
@@ -428,6 +428,7 @@ int PhaseChaitin::possibly_merge_multidef(Node *n, uint k, Block *block, RegToDe
// 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);
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index 0c31c9bc112..6096c98b29f 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -1127,7 +1127,7 @@ static void no_shared_spaces(const char* message) {
#endif
intx Arguments::scaled_compile_threshold(intx threshold, double scale) {
- if (scale == 1.0 || scale < 0.0) {
+ if (scale == 1.0 || scale <= 0.0) {
return threshold;
} else {
return (intx)(threshold * scale);
@@ -1143,7 +1143,7 @@ intx Arguments::scaled_freq_log(intx freq_log, double scale) {
// Check value to avoid calculating log2 of 0.
if (scale == 0.0) {
- return 1;
+ return freq_log;
}
intx scaled_freq = scaled_compile_threshold((intx)1 << freq_log, scale);
@@ -3479,8 +3479,10 @@ jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_req
set_mode_flags(_int);
}
- if ((TieredCompilation && CompileThresholdScaling == 0)
- || (!TieredCompilation && 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);
}
diff --git a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
index 5e611022762..257e70a5bcc 100644
--- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
+++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java
@@ -84,6 +84,13 @@ public class CheckCompileThresholdScaling {
"-XX:CompileThresholdScaling=0.75",
"-version"
},
+ {
+ "-XX:-TieredCompilation",
+ "-XX:+PrintFlagsFinal",
+ "-XX:CompileThreshold=1000",
+ "-XX:CompileThresholdScaling=0.0",
+ "-version"
+ },
{
"-XX:-TieredCompilation",
"-XX:+PrintFlagsFinal",
@@ -107,6 +114,11 @@ public class CheckCompileThresholdScaling {
"intx CompileThreshold := 750 {pd product}",
"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}",
@@ -295,21 +307,21 @@ public class CheckCompileThresholdScaling {
"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"
}
diff --git a/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java b/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java
index 74b21f1f19e..c07d3a331eb 100644
--- a/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java
+++ b/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java
@@ -82,6 +82,9 @@ public class PrintCodeCacheRunner implements CodeCacheCLITestCase.Runner {
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"));
}
}
diff --git a/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java
index 1a7ae636097..f51f296ee67 100644
--- a/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java
+++ b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java
@@ -36,7 +36,7 @@ public class CodeCacheStressRunner {
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);
diff --git a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java
index 5f52ef679ea..e759d499468 100644
--- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java
@@ -77,7 +77,7 @@ public class OverloadCompileQueueTest implements Runnable {
}
public OverloadCompileQueueTest() {
- Helper.startInfiniteLoopThread(this::lockUnlock);
+ Helper.startInfiniteLoopThread(this::lockUnlock, 100L);
}
@Override
@@ -99,8 +99,9 @@ public class OverloadCompileQueueTest implements Runnable {
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 {
diff --git a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java
index 8248582d38c..6d69b5e7dd4 100644
--- a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java
+++ b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java
@@ -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 @@ public class CheckCompileCommandOption {
// 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 @@ public class CheckCompileCommandOption {
"-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 @@ public class CheckCompileCommandOption {
out.shouldContain(expected_output);
}
- out.shouldNotContain("CompileCommand: unrecognized line");
+ out.shouldNotContain("CompileCommand: An error occured during parsing");
out.shouldHaveExitValue(0);
}
@@ -183,7 +207,7 @@ public class CheckCompileCommandOption {
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 @@ public class CheckCompileCommandOption {
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]);
+ }
}
}
diff --git a/hotspot/test/compiler/oracle/TestCompileCommand.java b/hotspot/test/compiler/oracle/TestCompileCommand.java
new file mode 100644
index 00000000000..e2575ed1fa5
--- /dev/null
+++ b/hotspot/test/compiler/oracle/TestCompileCommand.java
@@ -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]);
+ }
+ }
+}
diff --git a/hotspot/test/compiler/oracle/command1.txt b/hotspot/test/compiler/oracle/command1.txt
new file mode 100644
index 00000000000..aaf7cbdaecf
--- /dev/null
+++ b/hotspot/test/compiler/oracle/command1.txt
@@ -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
diff --git a/hotspot/test/compiler/oracle/command2.txt b/hotspot/test/compiler/oracle/command2.txt
new file mode 100644
index 00000000000..d6b5279c881
--- /dev/null
+++ b/hotspot/test/compiler/oracle/command2.txt
@@ -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
diff --git a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
index d27a87d8c2e..56a66d0804f 100644
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
+++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java
@@ -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 @@ public class TestRTMTotalCountIncrRate extends CommandLineOptionTest {
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();
diff --git a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java
index c08067ec4be..0f90d898625 100644
--- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java
+++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java
@@ -34,7 +34,6 @@ import com.oracle.java.testlibrary.InfiniteLoop;
/*
* @test
* @bug 8059624 8064669
- * @ignore 8066998
* @library /testlibrary /../../test/lib
* @build ForceNMethodSweepTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox
@@ -42,7 +41,7 @@ import com.oracle.java.testlibrary.InfiniteLoop;
* @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 {
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index c0eb212b48c..664424cb343 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -290,3 +290,4 @@ a12d347f84176200593999f4da91ae2bb86865b2 jdk9-b39
0dab3e848229127c7aca4c58b98e2d90ba70372f jdk9-b45
74eaf7ad986576c792df4dbff05eed63e5727695 jdk9-b46
e391de88e69b59d7c618387e3cf91032f6991ce9 jdk9-b47
+833051855168a973780fafeb6fc59e7370bcf400 jdk9-b48
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
index 74acd2ad341..8d05e9e8cf7 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java
@@ -270,8 +270,8 @@ public final class BasisLibrary {
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 final class BasisLibrary {
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;
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java
index dc64401eda6..a87728dc639 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java
@@ -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.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 com.sun.org.apache.xpath.internal.objects.XObject;
import javax.xml.namespace.QName;
-import javax.xml.xpath.XPathExpressionException;
+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.XPathFunctionResolver;
import javax.xml.xpath.XPathVariableResolver;
-import javax.xml.xpath.XPathConstants;
-
-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.w3c.dom.Node;
import org.xml.sax.InputSource;
/**
@@ -54,22 +39,10 @@ import org.xml.sax.InputSource;
*
* @author Ramesh Mandava
*/
-public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{
+public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression {
- private XPathFunctionResolver functionResolver;
- private XPathVariableResolver variableResolver;
- private JAXPPrefixResolver prefixResolver;
private com.sun.org.apache.xpath.internal.XPath xpath;
- // 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;
-
/** Protected constructor to prevent direct instantiation; use compile()
* from the context.
*/
@@ -81,7 +54,7 @@ public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{
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 @@ public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{
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 );
+ XObject resultObject = eval(item, xpath);
+ 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;
- }
-
-
- /**
- *
Evaluate the compiled XPath expression in the specified context and
- * return the result as the specified type.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If returnType is not one of the types defined
- * in {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
- *
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If returnType is null, then a
- * NullPointerException is thrown.
- *
- * @param item The starting context (node or node list, for example).
- * @param returnType The desired return type.
- *
- * @return The Object that is the result of evaluating the
- * expression and converting the result to
- * returnType.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If returnType is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If returnType is
- * null.
- */
+ @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);
}
}
-
}
- /**
- *
Evaluate the compiled XPath expression in the specified context and
- * return the result as a String.
- *
- *
This method calls {@link #evaluate(Object item, QName returnType)}
- * with a returnType of
- * {@link XPathConstants#STRING}.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- *
- * @param item The starting context (node or node list, for example).
- *
- * @return The String that is the result of evaluating the
- * expression and converting the result to a
- * String.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- */
+
+ @Override
public String evaluate(Object item)
throws XPathExpressionException {
- return (String)this.evaluate( item, XPathConstants.STRING );
+ return (String)this.evaluate(item, XPathConstants.STRING);
}
-
-
- static DocumentBuilderFactory dbf = null;
- static DocumentBuilder db = null;
- static Document d = null;
-
- /**
- *
Evaluate the compiled XPath expression in the context of the
- * specified InputSource and return the result as the
- * specified type.
- *
- *
This method builds a data model for the {@link InputSource} and calls
- * {@link #evaluate(Object item, QName returnType)} on the resulting
- * document object.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If returnType is not one of the types defined in
- * {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
- *
- *
If source or returnType is null,
- * then a NullPointerException is thrown.
- *
- * @param source The InputSource of the document to evaluate
- * over.
- * @param returnType The desired return type.
- *
- * @return The Object that is the result of evaluating the
- * expression and converting the result to
- * returnType.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws IllegalArgumentException If returnType is not one
- * of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If source or
- * returnType is null.
- */
+ @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);
}
}
- /**
- *
Evaluate the compiled XPath expression in the context of the specified InputSource and return the result as a
- * String.
- *
- *
This method calls {@link #evaluate(InputSource source, QName returnType)} with a returnType of
- * {@link XPathConstants#STRING}.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If source is null, then a NullPointerException is thrown.
- *
- * @param source The InputSource of the document to evaluate over.
- *
- * @return The String that is the result of evaluating the expression and converting the result to a
- * String.
- *
- * @throws XPathExpressionException If the expression cannot be evaluated.
- * @throws NullPointerException If source is null.
- */
+ @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 evaluateExpression(Object item, Class 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 evaluateExpression(InputSource source, Class type)
+ throws XPathExpressionException {
+ Document document = getDocument(source);
+ return evaluateExpression(document, type);
+ }
+
+ @Override
+ public XPathEvaluationResult> evaluateExpression(InputSource source)
+ throws XPathExpressionException {
+ return evaluateExpression(source, XPathEvaluationResult.class);
+ }
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
index ebd6b2c712f..1bbfef442ad 100644
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java
@@ -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.XPathConstants;
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 @@ public class XPathImpl implements javax.xml.xpath.XPath {
this.featureManager = featureManager;
}
- /**
- *
- *
- * @return Current function resolver
- */
+ //-Override-
public XPathFunctionResolver getXPathFunctionResolver() {
return functionResolver;
}
- /**
- *
Establishes a namespace context.
- *
- * @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);
}
- /**
- *
Returns the current namespace context.
- *
- * @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);
- }
- }
-
-
- 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;
- }
-
/**
- *
Evaluate an XPath expression in the specified context and return the result as the specified type.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If 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 IllegalArgumentException is thrown.
- *
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If expression or returnType is null, then a
- * NullPointerException is thrown.
- *
+ * Evaluate an {@code XPath} expression in the specified context.
* @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 Object of returnType.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If expression or returnType is null.
+ * @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);
+
+ return eval(contextItem, xpath);
+ }
+
+ //-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 );
- }
-
-
-
- /**
- *
Evaluate an XPath expression in the specified context and return the result as a String.
- *
- *
This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a returnType of
- * {@link XPathConstants#STRING}.
- *
- *
See "Evaluation of XPath Expressions" of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If expression is null, then a NullPointerException is thrown.
- *
- * @param expression The XPath expression.
- * @param item The starting context (node or node list, for example).
- *
- * @return The String that is the result of evaluating the expression and
- * converting the result to a String.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If expression is null.
- */
+ //-Override-
public String evaluate(String expression, Object item)
throws XPathExpressionException {
- return (String)this.evaluate( expression, item, XPathConstants.STRING );
+ return (String)this.evaluate(expression, item, XPathConstants.STRING);
}
- /**
- *
Compile an XPath expression for later evaluation.
- *
- *
If expression contains any {@link XPathFunction}s,
- * they must be available via the {@link XPathFunctionResolver}.
- * An {@link XPathExpressionException} will be thrown if the XPathFunction
- * cannot be resovled with the XPathFunctionResolver.
- *
- *
If expression is null, a NullPointerException is thrown.
- *
- * @param expression The XPath expression.
- *
- * @return Compiled XPath expression.
-
- * @throws XPathExpressionException If expression cannot be compiled.
- * @throws NullPointerException If expression is null.
- */
+ //-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) ;
}
}
-
- /**
- *
Evaluate an XPath expression in the context of the specified InputSource
- * and return the result as the specified type.
- *
- *
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.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If returnType is not one of the types defined in {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
- *
- *
If expression, source or returnType is null,
- * then a NullPointerException is thrown.
- *
- * @param expression The XPath expression.
- * @param source The input source of the document to evaluate over.
- * @param returnType The desired return type.
- *
- * @return The Object that encapsulates the result of evaluating the expression.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If expression, source or returnType
- * is null.
- */
+ //-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);
}
}
-
}
-
-
-
- /**
- *
Evaluate an XPath expression in the context of the specified InputSource
- * and return the result as a String.
- *
- *
This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * returnType of {@link XPathConstants#STRING}.
- *
- *
See "Evaluation of XPath Expressions" section of JAXP 1.3 spec
- * for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If expression or source is null,
- * then a NullPointerException is thrown.
- *
- * @param expression The XPath expression.
- * @param source The InputSource of the document to evaluate over.
- *
- * @return The String that is the result of evaluating the expression and
- * converting the result to a String.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If expression or source is null.
- */
+ //-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);
}
- /**
- *
Reset this XPath to its original configuration.
- *
- *
XPath is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * reset() is designed to allow the reuse of existing XPaths
- * thus saving resources associated with the creation of new XPaths.
- *
- *
The reset XPath is not guaranteed to have the same
- * {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} Objects, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal XPathFunctionResolver,
- * XPathVariableResolver
- * and NamespaceContext.
- */
+ //-Override-
public void reset() {
this.variableResolver = this.origVariableResolver;
this.functionResolver = this.origFunctionResolver;
this.namespaceContext = null;
}
+ //-Override-
+ public T evaluateExpression(String expression, Object item, Class 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 evaluateExpression(String expression, InputSource source, Class 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);
+ }
}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
new file mode 100644
index 00000000000..da4cdfc6f25
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java
@@ -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 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 getXPathResult(XObject resultObject, Class 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 The class type
+ * @param type The type to be checked
+ * @throws IllegalArgumentException if the type is not supported
+ */
+ void isSupportedClassType(Class 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 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}
+ */
+ 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);
+ }
+ }
+}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java
new file mode 100644
index 00000000000..14c291fc94d
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java
@@ -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 elementType;
+ NodeList nodeList = null;
+
+ public XPathNodesImpl(NodeList nodeList, Class elementType) {
+ this.nodeList = nodeList;
+ this.elementType = elementType;
+ }
+
+ @Override
+ public Iterator iterator() {
+ return new NodeSetIterator<>(elementType);
+ }
+
+ class NodeSetIterator implements Iterator {
+ int currentIndex;
+ Class elementType;
+ NodeSetIterator(Class 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;
+ }
+}
diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java
new file mode 100644
index 00000000000..4953702f4ba
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java
@@ -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 implements XPathEvaluationResult {
+
+ XObject resultObject;
+ int resultType;
+ Class 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 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 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 getValue(XObject resultObject, Class type) throws TransformerException {
+ Objects.requireNonNull(type);
+ if (type.isAssignableFrom(XPathEvaluationResult.class)) {
+ return type.cast(new XPathResultImpl(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 The expected class type.
+ * @param type the class type
+ * @return the internal XObject type.
+ */
+ static int classToInternalType(Class 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;
+ }
+}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
index 90ba4feac2a..6e77e23e441 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java
@@ -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.QName;
import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import org.xml.sax.InputSource;
/**
- *
XPath provides access to the XPath evaluation environment and expressions.
+ * {@code XPath} provides access to the XPath evaluation environment and expressions.
*
*
*
@@ -55,8 +54,8 @@ import javax.xml.namespace.NamespaceContext;
* 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 null for the variable.
- * The value of a variable must be immutable through the course of any single evaluation.
+ * the resolver returns {@code null} for the variable.
+ * The value of a variable must be immutable through the course of any single evaluation.
*
*
*
@@ -65,7 +64,7 @@ import javax.xml.namespace.NamespaceContext;
* 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 null for the function.
+ * the function resolver returns {@code null} for the function.
*
*
* 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.
+ * Conversion to the return type follows XPath conversion rules.
*
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 evaluate
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the evaluate method.
+ * the {@code evaluate} method.
*
*
* @author Norman Walsh
@@ -100,191 +99,189 @@ import javax.xml.namespace.NamespaceContext;
*/
public interface XPath {
- /**
- *
Reset this XPath to its original configuration.
- *
- *
XPath is reset to the same state as when it was created with
- * {@link XPathFactory#newXPath()}.
- * reset() is designed to allow the reuse of existing XPaths
- * thus saving resources associated with the creation of new XPaths.
- *
- *
The reset XPath is not guaranteed to have the same {@link XPathFunctionResolver}, {@link XPathVariableResolver}
- * or {@link NamespaceContext} Objects, e.g. {@link Object#equals(Object obj)}.
- * It is guaranteed to have a functionally equal XPathFunctionResolver, XPathVariableResolver
- * and NamespaceContext.
- */
- public void reset();
/**
- *
Establish a variable resolver.
+ * Reset this {@code XPath} to its original configuration.
*
- *
A NullPointerException is thrown if resolver is null.
+ *
{@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.
+ *
+ *
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.
+ *
+ *
A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver Variable resolver.
*
- * @throws NullPointerException If resolver is null.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathVariableResolver(XPathVariableResolver resolver);
/**
- *
Return the current variable resolver.
+ * Return the current variable resolver.
*
- *
null is returned in no variable resolver is in effect.
+ *
{@code null} is returned in no variable resolver is in effect.
*
* @return Current variable resolver.
*/
public XPathVariableResolver getXPathVariableResolver();
/**
- *
Establish a function resolver.
+ * Establish a function resolver.
*
- *
A NullPointerException is thrown if resolver is null.
+ *
A {@code NullPointerException} is thrown if {@code resolver} is {@code null}.
*
* @param resolver XPath function resolver.
*
- * @throws NullPointerException If resolver is null.
+ * @throws NullPointerException If {@code resolver} is {@code null}.
*/
public void setXPathFunctionResolver(XPathFunctionResolver resolver);
/**
- *
Return the current function resolver.
- *
- *
null is returned in no function resolver is in effect.
+ * Return the current function resolver.
+ *
+ * {@code null} is returned in no function resolver is in effect.
*
* @return Current function resolver.
*/
public XPathFunctionResolver getXPathFunctionResolver();
/**
- *
Establish a namespace context.
+ * Establish a namespace context.
*
- *
A NullPointerException is thrown if nsContext is null.
+ *
A {@code NullPointerException} is thrown if {@code nsContext} is {@code null}.
*
* @param nsContext Namespace context to use.
*
- * @throws NullPointerException If nsContext is null.
+ * @throws NullPointerException If {@code nsContext} is {@code null}.
*/
public void setNamespaceContext(NamespaceContext nsContext);
/**
- *
Return the current namespace context.
+ * Return the current namespace context.
*
- *
null is returned in no namespace context is in effect.
+ *
{@code null} is returned in no namespace context is in effect.
*
* @return Current Namespace context.
*/
public NamespaceContext getNamespaceContext();
/**
- *
Compile an XPath expression for later evaluation.
+ * Compile an XPath expression for later evaluation.
*
- *
If expression contains any {@link XPathFunction}s,
+ *
If {@code expression} contains any {@link XPathFunction}s,
* they must be available via the {@link XPathFunctionResolver}.
* An {@link XPathExpressionException} will be thrown if the
- * XPathFunction
- * cannot be resovled with the XPathFunctionResolver.
+ * {@code XPathFunction}
+ * cannot be resovled with the {@code XPathFunctionResolver}.
*
- *
If expression contains any variables, the
+ *
If {@code expression} contains any variables, the
* {@link XPathVariableResolver} in effect
- * at compile time will be used to resolve them.
- *
- *
If expression is null, a NullPointerException is thrown.
+ * at compile time will be used to resolve them.
*
* @param expression The XPath expression.
*
* @return Compiled XPath expression.
- * @throws XPathExpressionException If expression cannot be compiled.
- * @throws NullPointerException If expression is null.
+ * @throws XPathExpressionException If {@code expression} cannot be compiled.
+ * @throws NullPointerException If {@code expression} is {@code null}.
*/
public XPathExpression compile(String expression)
throws XPathExpressionException;
/**
- *
Evaluate an XPath expression in the specified context and return the result as the specified type.
+ * Evaluate an {@code XPath} expression in the specified context and
+ * return the result as the specified type.
*
- *
See Evaluation of XPath Expressions for context item evaluation,
- * variable, function and QName resolution and return type conversion.
+ *
+ * See Evaluation of XPath Expressions
+ * for context item evaluation, variable, function and {@code QName} resolution
+ * and return type conversion.
+ *
+ * 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.
*
- *
If returnType 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 IllegalArgumentException is thrown.
- *
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If expression or returnType is null, then a
- * NullPointerException is thrown.
- *
- * @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 Object of returnType.
- *
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws IllegalArgumentException If returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If expression or returnType is null.
+ * {@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;
/**
- *
Evaluate an XPath expression in the specified context and return the result as a String.
+ * Evaluate an XPath expression in the specified context and return the result as a {@code String}.
*
- *
This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a returnType of
- * {@link XPathConstants#STRING}.
+ *
This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a {@code returnType} of
+ * {@link XPathConstants#STRING}.
*
*
See Evaluation of XPath Expressions for context item evaluation,
- * variable, function and QName resolution and return type conversion.
+ * variable, function and QName resolution and return type conversion.
*
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If expression is null, then a NullPointerException is thrown.
+ *
+ * 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 String that is the result of evaluating the expression and
- * converting the result to a String.
+ * @return The result of evaluating an XPath expression as a {@code String}.
*
- * @throws XPathExpressionException If expression cannot be evaluated.
- * @throws NullPointerException If expression is null.
+ * @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;
/**
- *
Evaluate an XPath expression in the context of the specified InputSource
- * and return the result as the specified type.
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as the specified type.
*
*
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.
+ * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.
*
*
See Evaluation of XPath Expressions for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If returnType is not one of the types defined in {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
- *
- *
If expression, source or returnType is null,
- * then a NullPointerException is thrown.
+ * 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 Object 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 returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If expression, source or returnType
- * is null.
+ * @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 @@ public interface XPath {
throws XPathExpressionException;
/**
- *
Evaluate an XPath expression in the context of the specified InputSource
- * and return the result as a String.
+ * Evaluate an XPath expression in the context of the specified {@code InputSource}
+ * and return the result as a {@code String}.
*
*
This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a
- * returnType of {@link XPathConstants#STRING}.
+ * {@code returnType} of {@link XPathConstants#STRING}.
*
*
See Evaluation of XPath Expressions for context item evaluation,
- * variable, function and QName resolution and return type conversion.
- *
- *
If expression or source is null,
- * then a NullPointerException is thrown.
+ * variable, function and QName resolution and return type conversion.
*
* @param expression The XPath expression.
- * @param source The InputSource of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The String that is the result of evaluating the expression and
- * converting the result to a String.
+ * @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 expression or source is null.
+ * @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}
+ *
+ *
+ * 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:
+ *
+ *
+ * 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 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 evaluateExpression(String expression, Object item, Class 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}:
+ *
+ * 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:
+ *
+ *
+ * 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.
+ *
+ * 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:
+ *
+ *
+ * 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 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 evaluateExpression(String expression, InputSource source, Class 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}:
+ *
+ *
+ * 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);
+ }
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java
new file mode 100644
index 00000000000..745473975e5
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java
@@ -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.
+ *
+ *
+ * @param the object type returned by the XPath evaluation.
+ * @see XML Path Language (XPath) Version
+ * 1.0
+ *
+ * @since 1.9
+ */
+public interface XPathEvaluationResult {
+
+ /**
+ * 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();
+
+}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
index 0f980f6ed8e..a7625ec1b87 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java
@@ -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 org.xml.sax.InputSource;
import javax.xml.namespace.QName;
+import org.xml.sax.InputSource;
/**
- *
XPathExpression provides access to compiled XPath expressions.
+ *
{@code XPathExpression} provides access to compiled XPath expressions.
* 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 null 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.
*
* 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 null for the function.
+ * the function resolver returns {@code null} for the function.
*
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 evaluate
+ * more than one thread at any given time, and while the {@code evaluate}
* method is invoked, applications may not recursively call
- * the evaluate method.
+ * the {@code evaluate} method.
*
*
* @author Norman Walsh
@@ -96,50 +96,56 @@ import javax.xml.namespace.QName;
*/
public interface XPathExpression {
+
/**
*
Evaluate the compiled XPath expression in the specified context and return the result as the specified type.
*
*
See Evaluation of XPath Expressions for context item evaluation,
* variable, function and QName resolution and return type conversion.
*
- *
If returnType is not one of the types defined in {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
+ *
+ * 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.
*
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
- * If returnType is null, then a NullPointerException is thrown.
+ * @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 Object that is the result of evaluating the expression and converting the result to
- * returnType.
+ * @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 returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If returnType is null.
+ * @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;
/**
- *
Evaluate the compiled XPath expression in the specified context and return the result as a String.
+ *
Evaluate the compiled XPath expression in the specified context and return the result as a {@code String}.
*
- *
This method calls {@link #evaluate(Object item, QName returnType)} with a returnType of
+ *
This method calls {@link #evaluate(Object item, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.
*
*
See Evaluation of XPath Expressions for context item evaluation,
* variable, function and QName resolution and return type conversion.
*
- *
If a null value is provided for
- * item, an empty document will be used for the
- * context.
+ *
+ * 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 String that is the result of evaluating the expression and converting the result to a
- * String.
+ * @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 @@ public interface XPathExpression {
throws XPathExpressionException;
/**
- *
Evaluate the compiled XPath expression in the context of the specified InputSource and return the result as the
+ *
Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as the
* specified type.
*
*
This method builds a data model for the {@link InputSource} and calls
@@ -156,45 +162,225 @@ public interface XPathExpression {
*
See Evaluation of XPath Expressions for context item evaluation,
* variable, function and QName resolution and return type conversion.
*
- *
If returnType is not one of the types defined in {@link XPathConstants},
- * then an IllegalArgumentException is thrown.
+ *
If {@code returnType} is not one of the types defined in {@link XPathConstants},
+ * then an {@code IllegalArgumentException} is thrown.
*
- *
If source or returnType is null,
- * then a NullPointerException is thrown.
+ *
If {@code source} or {@code returnType} is {@code null},
+ * then a {@code NullPointerException} is thrown.
*
- * @param source The InputSource 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 Object that is the result of evaluating the expression and converting the result to
- * returnType.
+ * @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 returnType is not one of the types defined in {@link XPathConstants}.
- * @throws NullPointerException If source or returnType is null.
+ * @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;
/**
- *
Evaluate the compiled XPath expression in the context of the specified InputSource and return the result as a
- * String.
+ *
Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as a
+ * {@code String}.
*
- *
This method calls {@link #evaluate(InputSource source, QName returnType)} with a returnType of
+ *
This method calls {@link #evaluate(InputSource source, QName returnType)} with a {@code returnType} of
* {@link XPathConstants#STRING}.
*
*
See Evaluation of XPath Expressions for context item evaluation,
* variable, function and QName resolution and return type conversion.
*
- *
If source is null, then a NullPointerException is thrown.
+ *
If {@code source} is {@code null}, then a {@code NullPointerException} is thrown.
*
- * @param source The InputSource of the document to evaluate over.
+ * @param source The {@code InputSource} of the document to evaluate over.
*
- * @return The String that is the result of evaluating the expression and converting the result to a
- * String.
+ * @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 source is null.
+ * @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}.
+ *
+ *
+ * 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:
+ *
+ *
+ * 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 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 evaluateExpression(Object item, Class 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}:
+ *
+ * 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:
+ *
+ *
+ * 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}
+ *
+ * This method builds a data model for the {@link InputSource} and calls
+ * {@link #evaluateExpression(Object item, Class type)} on the resulting
+ * document object.
+ *
+ * By default, the JDK's data model is {@link org.w3c.dom.Document}.
+ *
+ * @implSpec
+ * The default implementation in the XPath API is equivalent to:
+ *
+ *
+ * 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 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 evaluateExpression(InputSource source, Class 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}:
+ *
+ *
+ * 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);
+ }
}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
index ce2074b19a3..ea7370e06e7 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java
@@ -117,7 +117,7 @@ public abstract class XPathFactory {
* and returns it if it is successfully created.
*
*
- * ${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.
*
*
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java
index 282f0b05d61..bceeda854e8 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java
@@ -176,9 +176,9 @@ class XPathFactoryFinder {
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 @@ class XPathFactoryFinder {
}
}
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);
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java
new file mode 100644
index 00000000000..6f1db4e0d45
--- /dev/null
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java
@@ -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 XML Path Language (XPath)
+ * Version 1.0, 3.3 Node-sets.
+ *
+ * @since 1.9
+ */
+public interface XPathNodes extends Iterable {
+
+ /**
+ * Returns an iterator of the Nodes.
+ *
+ * @return an Iterator.
+ */
+ @Override
+ public abstract Iterator 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;
+}
diff --git a/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html b/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html
index 82415a2d407..af0d152bc58 100644
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html
+++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html
@@ -1,6 +1,8 @@
-
+
+
+
-
-
-
-
-javax.xml.xpath
-
-
-
-
-
+
-
-
-
This package provides an object-model neutral API for the
+This package provides an object-model neutral API for the
evaluation of XPath expressions and access to the evaluation
environment.
-
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 @@ stand-alone language, as a single XPath expression can be used to
replace many lines of DOM API code.
-
XPath Expressions
+
+
2. XPath Expressions
An XPath expression is composed of a location
path and one or more optional predicates. Expressions
@@ -76,18 +79,22 @@ may also include XPath variables.
The following is an example of a simple XPath expression:
+
/foo/bar
+
This example would select the <bar> element in
an XML document such as the following:
+
<foo>
-<bar/>
+ <bar/>
</foo>
+
The expression /foo/bar is an example of a location
path. While XPath location paths resemble Unix-style file system
@@ -96,30 +103,36 @@ paths, an important distinction is that XPath expressions return
<bar> elements in the following document would be
selected by the /foo/bar expression:
A special location path operator, //, selects nodes at
any depth in an XML document. The following example selects all
<bar> elements regardless of their location in a
document:
+
//bar
+
A wildcard operator, *, causes all element nodes to be selected.
The following example selects all children elements of a
-<foo> element:
+<foo> element:
+
/foo/*
+
In addition to element nodes, XPath location paths may also address
attribute nodes, text nodes, comment nodes, and processing instruction
@@ -166,35 +179,27 @@ location path. Predicates are of the form
<foo> elements that contain an include
attribute with the value of true:
+
//foo[@include='true']
+
Predicates may be appended to each other to further refine an
expression, such as:
+
//foo[@include='true'][@mode='bar']
+
-
Using the XPath API
-
-
-The following example demonstrates using the XPath API to select one
-or more nodes from an XML document:
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:
+following data types:
Boolean
@@ -202,14 +207,10 @@ following other data types:
String
-
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
-XPathExpression.evalute(...) or to one of the
-XPath.evaluate(...) convenience methods. The allowed
-QName values are specified as constants in the {@link
-javax.xml.xpath.XPathConstants} class; they are:
-
+
+
3.1 QName types
+The XPath API defines the following {@link javax.xml.namespace.QName} types to
+represent return types of an XPath evaluation:
{@link javax.xml.xpath.XPathConstants#NODESET}
{@link javax.xml.xpath.XPathConstants#NODE}
@@ -218,26 +219,71 @@ javax.xml.xpath.XPathConstants} class; they are:
{@link javax.xml.xpath.XPathConstants#NUMBER}
+
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
+XPathExpression.evalute(...) or XPath.evaluate(...)
+methods.
+
When a Boolean return type is requested,
Boolean.TRUE is returned if one or more nodes were
-selected; otherwise, Boolean.FALSE is returned.
+selected; otherwise, Boolean.FALSE is returned.
The String 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.
-
The Number return type attempts to coalesce the text
of a node to a double data type.
-
-
XPath Context
+
+
3.2 Class types
+In addition to the QName types, the XPath API supports the use of Class types
+through the XPathExpression.evaluteExpression(...) or
+XPath.evaluateExpression(...) methods.
+
+The XPath data types are mapped to Class types as follows:
+
+
Boolean -- Boolean.class
+
Number -- Number.class
+
String -- String.class
+
Nodeset -- XPathNodes.class
+
Node -- Node.class
+
+
+
+Of the subtypes of Number, only Double, Integer and Long are supported.
+
+
+
3.3 Enum types
+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 XPathExpression.evaluteExpression(...)
+or XPath.evaluateExpression(...) methods will be of one of these types.
+
+
+
4. XPath Context
XPath location paths may be relative to a particular node in the
-document, known as the context. Consider the following
-XML document:
+document, known as the context. A context consists of:
+
+
a node (the context node)
+
a pair of non-zero positive integers (the context position and the context size)
+
a set of variable bindings
+
a function library
+
the set of namespace declarations in scope for the expression
+
+
+It is an XML document tree represented as a hierarchy of nodes, a
+{@link org.w3c.dom.Node} for example, in the JDK implementation.
+
+
+
5. Using the XPath API
+
+Consider the following XML document:
+
+
<widgets>
<widget>
@@ -246,36 +292,88 @@ XML document:
</widget>
</widgets>
+
-
The <widget> element can be selected with the
-following XPath API code:
+
+The <widget> element can be selected with the following process:
+
// 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);
+
With a reference to the <widget> element, a
-relative XPath expression can now written to select the
+relative XPath expression can be written to select the
<manufacturer> child element:
+//or using the evaluateExpression method
+Node manufacturerNode = xpath.evaluateExpression(expression, widgetNode, Node.class);
+
+
+
+
+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:
+
+
+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:
+
+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:
+
+
+@since 1.5
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
new file mode 100644
index 00000000000..de285f21aa8
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java
@@ -0,0 +1,297 @@
+/*
+ * 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 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"));
+ }
+
+ @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 SchemaFactory sf;
+ private byte[] xsd1;
+ private byte[] xsd2;
+ private Document xsdDoc1;
+ private Document xsdDoc2;
+ private byte[] xml;
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/TypeInfoProviderTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/TypeInfoProviderTest.java
new file mode 100644
index 00000000000..d34c708bc90
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/TypeInfoProviderTest.java
@@ -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));
+ }
+
+ }
+
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorHandlerTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorHandlerTest.java
new file mode 100644
index 00000000000..3b48a21203f
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorHandlerTest.java
@@ -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;
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorTest.java b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorTest.java
new file mode 100644
index 00000000000..c455f070694
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorTest.java
@@ -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;
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xml b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xml
new file mode 100644
index 00000000000..0a00dbdaae0
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xml
@@ -0,0 +1,24 @@
+
+
+
+John Smith
+
+Ola Nordmann
+Langgt 23
+4000 Stavanger
+Norway
+
+
+Empire Burlesque
+Special Edition
+1
+10.90
+
+
+Hide your heart
+1
+9.90
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xsd b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xsd
new file mode 100644
index 00000000000..7281dbd9698
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xsd
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xml b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xml
new file mode 100644
index 00000000000..0a00dbdaae0
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xml
@@ -0,0 +1,24 @@
+
+
+
+John Smith
+
+Ola Nordmann
+Langgt 23
+4000 Stavanger
+Norway
+
+
+Empire Burlesque
+Special Edition
+1
+10.90
+
+
+Hide your heart
+1
+9.90
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xsd b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xsd
new file mode 100644
index 00000000000..7281dbd9698
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xsd
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xml b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xml
new file mode 100644
index 00000000000..8ad28618d01
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xml
@@ -0,0 +1,5 @@
+
+
+ John
+444-121-3434
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xsd b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xsd
new file mode 100644
index 00000000000..1671283691c
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xsd
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test1.xsd b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test1.xsd
new file mode 100644
index 00000000000..9f172d23639
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test1.xsd
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4511326.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4511326.java
new file mode 100644
index 00000000000..fec94a13174
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4511326.java
@@ -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 = ""
+ + ""
+ + "
"
+ + "
"
+ + ""
+ + "";
+
+
+ @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);
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4512806.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4512806.java
new file mode 100644
index 00000000000..631b0919ec7
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4512806.java
@@ -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 = ""
+ + "\n"
+ + " \n"
+ + " \n"
+ + " Hello World! \n"
+ + " \n"
+ + "";
+
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515047.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515047.java
new file mode 100644
index 00000000000..0b822c810ef
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515047.java
@@ -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);
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515660.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515660.java
new file mode 100644
index 00000000000..6f2c3140555
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515660.java
@@ -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 = "";
+ 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 = "\n" + "\n"
+ + " Hello World!\n" + "\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);
+ }
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4693341.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4693341.java
new file mode 100644
index 00000000000..d7d586b584c
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4693341.java
@@ -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));
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4848653.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4848653.java
new file mode 100644
index 00000000000..f4de7753162
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4848653.java
@@ -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;
+ }
+
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4858685.java b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4858685.java
new file mode 100644
index 00000000000..5dd54017c62
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4858685.java
@@ -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);
+ }
+
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.dtd b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.dtd
new file mode 100644
index 00000000000..23e6411665d
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.dtd
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.xml b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.xml
new file mode 100644
index 00000000000..96fad2304ec
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.xml
@@ -0,0 +1,20 @@
+
+
+
+10016
+Wed May 29 12:45:00 PDT 2002
+
+ABC
+XYZ
+1234 Anywhere Street
+Palo Alto
+California
+USA
+94303
+NULL
+NULL
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4848653.xml b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4848653.xml
new file mode 100644
index 00000000000..d80a5e273cc
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4848653.xml
@@ -0,0 +1 @@
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/certificate.xml b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/certificate.xml
new file mode 100644
index 00000000000..e56e16a0abb
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/certificate.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+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
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.dtd b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.dtd
new file mode 100644
index 00000000000..23e6411665d
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.dtd
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.xml b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.xml
new file mode 100644
index 00000000000..96fad2304ec
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.xml
@@ -0,0 +1,20 @@
+
+
+
+10016
+Wed May 29 12:45:00 PDT 2002
+
+ABC
+XYZ
+1234 Anywhere Street
+Palo Alto
+California
+USA
+94303
+NULL
+NULL
+
+
+
+
+
diff --git a/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4858685.txt b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4858685.txt
new file mode 100644
index 00000000000..91ee2de9052
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4858685.txt
@@ -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]
+
diff --git a/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/MyErrorHandler.java b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/MyErrorHandler.java
new file mode 100644
index 00000000000..1efbf95749f
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/MyErrorHandler.java
@@ -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;
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/ValidationTestConst.java b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/ValidationTestConst.java
new file mode 100644
index 00000000000..50f4c86d0e5
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/ValidationTestConst.java
@@ -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");
+}
diff --git a/jaxp/test/javax/xml/jaxp/libs/test/gaptest/GapTestConst.java b/jaxp/test/javax/xml/jaxp/libs/test/gaptest/GapTestConst.java
new file mode 100644
index 00000000000..237d0ac6ed2
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/libs/test/gaptest/GapTestConst.java
@@ -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");
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java
new file mode 100644
index 00000000000..ef56ca90d6d
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java
@@ -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 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");
+ }
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java
new file mode 100644
index 00000000000..0eb8047d14a
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java
@@ -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");
+ }
+
+}
diff --git a/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java
new file mode 100644
index 00000000000..0f0624216c8
--- /dev/null
+++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java
@@ -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
+ = ""
+ + ""
+ + " "
+ + " name1"
+ + " 1111111111"
+ + " 123@xyz.com"
+ + " "
+ + " 1111 111st ave"
+ + " The City"
+ + " The State"
+ + " "
+ + " "
+ + " "
+ + " name1"
+ + " 2222222222"
+ + " 123@xyz.com"
+ + " "
+ + " 2222 222nd ave"
+ + " The City"
+ + " The State"
+ + " "
+ + " "
+ + " "
+ + " name1"
+ + " 3333333333"
+ + " 123@xyz.com"
+ + " "
+ + " 3333 333rd ave"
+ + " The City"
+ + " The State"
+ + " "
+ + " "
+ + "";
+
+ 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}};
+ }
+}
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index 2f346d3cdf5..aab4c7697f1 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -293,3 +293,4 @@ edc13d27dc871be57d7ca77eef77e6d04972fee2 jdk9-b43
e529374fbe526dbd668e5e98fc047b42b3bc6d33 jdk9-b45
64ca52b0bda8028636e4ccafbe1107befcdda47d jdk9-b46
6c17d648d03e4bf4729c3645f8db55d34115e0b7 jdk9-b47
+33e7e699804892c0496adf60ad67cc12855aeb61 jdk9-b48
diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java
index eef5caf28a6..a15b1453e9f 100644
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java
+++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java
@@ -135,7 +135,7 @@ public class SchemaGenerator extends AbstractProcessor {
private void filterClass(List 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()));
}
diff --git a/jdk/.hgtags b/jdk/.hgtags
index e5ebdf47f06..c5a3e91f84e 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -290,3 +290,4 @@ e336cbd8b15e959e70ed02f0f5e93fa76ebd4c07 jdk9-b41
9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45
efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46
b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47
+ebb2eb7f1aec78eb6d8cc4c96f018afa11093cde jdk9-b48
diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk
index 55273f64299..32174efec0c 100644
--- a/jdk/make/Tools.gmk
+++ b/jdk/make/Tools.gmk
@@ -34,28 +34,23 @@ include JavaCompilation.gmk
include NativeCompilation.gmk
include SetupJavaCompilers.gmk
-# The exception handling of swing beaninfo which have the own tool directory
-ifeq (, $(BUILD_TOOLS_JDK))
- $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
- SETUP := GENERATE_OLDBYTECODE, \
- ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
- SRC := $(JDK_TOPDIR)/make/src/classes, \
- BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
- COPY := boot.modules ext.modules))
-endif
+################################################################################
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/%.template: \
- $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/%.template
- $(call install-file)
+$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
+ SETUP := GENERATE_OLDBYTECODE, \
+ ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
+ SRC := $(JDK_TOPDIR)/make/src/classes, \
+ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
+ COPY := boot.modules ext.modules))
-BUILD_TOOLS_JDK += $(foreach i, $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template), $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/$(notdir $i))
+$(eval $(call SetupCopyFiles,COPY_NIMBUS_TEMPLATES, \
+ SRC := $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus, \
+ DEST := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources, \
+ FILES := $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template)))
-# Resource used by CheckDeps tool
-$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed: \
- $(JDK_TOPDIR)/make/data/checkdeps/refs.allowed
- $(call install-file)
+BUILD_TOOLS_JDK += $(COPY_NIMBUS_TEMPLATES)
-BUILD_TOOLS_JDK += $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed
+################################################################################
# Add a checksum ("jsum") to the end of a text file. Prevents trivial tampering with class lists.
TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
@@ -130,10 +125,6 @@ TOOL_OSX_TOBIN = $(JAVA_SMALL) -Djava.awt.headless=true -cp $(BUILDTOOLS_OUTPUTD
TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
build.tools.cldrconverter.CLDRConverter
-TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
- -cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
- build.tools.deps.CheckDeps
-
TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
-cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
build.tools.module.GenJdepsModulesXml
@@ -161,25 +152,25 @@ $(eval $(call SetupJavaCompilation,BUILD_INTERIM_JIMAGE, \
# Tools needed on solaris because OBJCOPY is broken.
ifeq ($(OPENJDK_TARGET_OS), solaris)
-$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
- SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
- LDFLAGS := -lelf, \
- OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
- OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
- PROGRAM := add_gnu_debuglink))
+ $(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
+ SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
+ LANG := C, \
+ CC := $(BUILD_CC), \
+ LDEXE := $(BUILD_LD), \
+ LDFLAGS := -lelf, \
+ OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
+ OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+ PROGRAM := add_gnu_debuglink))
-$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
- SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
- LANG := C, \
- CC := $(BUILD_CC), \
- LDEXE := $(BUILD_LD), \
- LDFLAGS := -lelf, \
- OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
- OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
- PROGRAM := fix_empty_sec_hdr_flags))
+ $(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
+ SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
+ LANG := C, \
+ CC := $(BUILD_CC), \
+ LDEXE := $(BUILD_LD), \
+ LDFLAGS := -lelf, \
+ OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
+ OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
+ PROGRAM := fix_empty_sec_hdr_flags))
endif
$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE)
diff --git a/jdk/make/data/checkdeps/refs.allowed b/jdk/make/data/checkdeps/refs.allowed
deleted file mode 100644
index 7c15a04d91b..00000000000
--- a/jdk/make/data/checkdeps/refs.allowed
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# This properties-formatted file contains the names of the non-existent types
-# that are allowed to be referenced from classes in a profiles image.
-#
-# The property key is a type that does not exist. The property value is one or
-# more types that reference the missing type. The property value also encodes
-# the names of the profiles where this reference is allowed.
-
-# jsse.jar is not subsetted by the profiles build. For compact1 and compact2
-# then this means that there are references to Kerberos types that do not
-# exist. These references are harmless.
-#
-javax.security.auth.kerberos.KerberosKey=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosPrincipal=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.KerberosTicket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-javax.security.auth.kerberos.KeyTab=sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-javax.security.auth.kerberos.ServicePermission=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.GSSCaller=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.Krb5Util=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
-sun.security.jgss.krb5.ServiceCreds=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptedData= sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.EncryptionKey=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.crypto.KeyUsage=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.EncTicketPart=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Krb5=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.internal.Ticket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.KrbException=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.PrincipalName=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
-
-# Residual references to java.beans.
-# The RemoveMethods tool does not yet purge the constant pool.
-#
-java.beans.PropertyChangeListener=java.util.logging.LogManager,compact1,compact2,compact3
diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk
index f8ed6b172a7..c0489f3a97d 100644
--- a/jdk/make/gensrc/GensrcMisc.gmk
+++ b/jdk/make/gensrc/GensrcMisc.gmk
@@ -28,6 +28,13 @@
# string and the runtime name into the Version.java file.
# To be printed by java -version
+# These dependencies should ideally be added to prerequesites for Version.java
+# but skip for now until we have better incremental build for java.
+# $(call DependOnVariable, LAUNCHER_NAME) \
+# $(call DependOnVariable, RELEASE) \
+# $(call DependOnVariable, FULL_VERSION) \
+# $(call DependOnVariable, RUNTIME_VERSION)
+
$(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java: \
$(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template
$(MKDIR) -p $(@D)
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 30e3284a27d..026a6876efb 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -74,8 +74,6 @@ endif
##########################################################################################
-BUILD_LIBVERIFY_SRC := check_code.c check_format.c
-
ifeq ($(OPENJDK_TARGET_OS), solaris)
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
BUILD_LIBVERIFY_REORDER := $(JDK_TOPDIR)/make/mapfiles/libverify/reorder-$(OPENJDK_TARGET_CPU)
@@ -116,10 +114,6 @@ TARGETS += $(BUILD_LIBVERIFY)
LIBJAVA_SRC_DIRS := $(call FindSrcDirsForLib, java.base, java)
-ifeq ($(OPENJDK_TARGET_OS), macosx)
- LIBJAVA_EXCLUDE_FILES += $(JDK_TOPDIR)/src/java.base/unix/native/libjava/HostLocaleProviderAdapter_md.c
-endif
-
LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \
-I$(JDK_TOPDIR)/src/java.base/share/native/libfdlibm \
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
@@ -134,9 +128,7 @@ ifneq (, $(JDK_UPDATE_VERSION))
LIBJAVA_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"'
endif
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- LIBJAVA_EXCLUDE_FILES += java_props_macosx.c
-else
+ifeq ($(OPENJDK_TARGET_OS), macosx)
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
endif
@@ -151,8 +143,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
LIBRARY := java, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBJAVA_SRC_DIRS), \
- EXCLUDES := fdlibm/src zip prefs, \
- EXCLUDE_FILES := $(LIBJAVA_EXCLUDE_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
@@ -247,19 +237,10 @@ TARGETS += $(BUILD_LIBZIP)
##########################################################################################
-BUILD_LIBJLI_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libjli \
- $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli
+LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli)
LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
-BUILD_LIBJLI_FILES := \
- java.c \
- splashscreen_stubs.c \
- parse_manifest.c \
- version_comp.c \
- wildcard.c \
- jli_util.c
-
ifeq ($(JVM_VARIANT_ZERO), true)
ERGO_FAMILY := zero
else
@@ -269,68 +250,55 @@ else
ERGO_FAMILY := $(OPENJDK_TARGET_CPU_ARCH)
endif
endif
+LIBJLI_ALL_ERGO := $(wildcard $(addsuffix /ergo_*.c, $(LIBJLI_SRC_DIRS)))
+LIBJLI_EXCLUDE_ERGO := $(filter-out %/ergo_$(ERGO_FAMILY).c, $(LIBJLI_ALL_ERGO))
+# If all specialized ergo files are excluded, use generic ergo
+ifeq ($(LIBJLI_ALL_ERGO), $(LIBJLI_EXCLUDE_ERGO))
+ LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
+endif
+LIBJLI_EXCLUDE_FILES += $(notdir $(LIBJLI_EXCLUDE_ERGO))
ifeq ($(OPENJDK_TARGET_OS), macosx)
- BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/macosx/native/libjli
- BUILD_LIBJLI_FILES += java_md_common.c java_md_macosx.c
+ LIBJLI_EXCLUDE_FILES += java_md_solinux.c ergo.c
BUILD_LIBJLI_java_md_macosx.c_CFLAGS := -x objective-c
BUILD_LIBJLI_STATIC_java_md_macosx.c_CFLAGS := -x objective-c
-endif
-ifeq ($(OPENJDK_TARGET_OS), windows)
- BUILD_LIBJLI_FILES += java_md.c \
- cmdtoargs.c
- # Staticically link with c runtime on windows.
- LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
-else ifneq ($(OPENJDK_TARGET_OS), macosx)
-
- BUILD_LIBJLI_FILES += java_md_common.c
- BUILD_LIBJLI_FILES += java_md_solinux.c ergo.c
-
- ERGO_ARCH_FILE = ergo_$(ERGO_FAMILY).c
-
- # if the architecture specific ergo file exists then
- # use it, else use the generic definitions from ergo.c
- ifneq ($(wildcard $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli/$(ERGO_ARCH_FILE)), )
- BUILD_LIBJLI_FILES += $(ERGO_ARCH_FILE)
- else # !ERGO_ARCH_FILE
- LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
- endif # ERGO_ARCH_FILE
-endif #WINDOWS
-
-LIBJLI_CFLAGS += $(foreach dir, $(BUILD_LIBJLI_SRC_DIRS), -I$(dir))
-
-# Append defines depending on target platform
-LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
-
-ifeq ($(OPENJDK_TARGET_OS), macosx)
LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
endif
-ifneq ($(USE_EXTERNAL_LIBZ), true)
- BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8
- LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
- BUILD_LIBJLI_FILES += \
- inflate.c \
- inftrees.c \
- inffast.c \
- zadler32.c \
- zcrc32.c \
- zutil.c
-endif
-
ifeq ($(OPENJDK_TARGET_OS), windows)
+ # Staticically link with c runtime on windows.
+ LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)
else
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli
endif
+LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
+
+# Append defines depending on target platform
+LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
+
+ifneq ($(USE_EXTERNAL_LIBZ), true)
+ LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
+ LIBJLI_EXTRA_FILES += \
+ $(addprefix $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8/, \
+ inflate.c \
+ inftrees.c \
+ inffast.c \
+ zadler32.c \
+ zcrc32.c \
+ zutil.c \
+ )
+endif
+
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
LIBRARY := jli, \
OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(LIBJLI_CFLAGS), \
@@ -376,8 +344,9 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
STATIC_LIBRARY := jli_static, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
@@ -395,8 +364,9 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
LIBRARY := jli_static, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
- SRC := $(BUILD_LIBJLI_SRC_DIRS), \
- INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
@@ -411,16 +381,17 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
else ifeq ($(OPENJDK_TARGET_OS), aix)
# AIX also requires a static libjli because the compiler doesn't support '-rpath'
- $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC,\
- STATIC_LIBRARY:=jli_static,\
- OUTPUT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE),\
- SRC:=$(BUILD_LIBJLI_SRC_DIRS),\
- INCLUDE_FILES:=$(BUILD_LIBJLI_FILES),\
- LANG:=C,\
- OPTIMIZATION:=HIGH, \
- CFLAGS:=$(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS),\
- ARFLAGS:=$(ARFLAGS),\
- OBJECT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
+ $(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
+ STATIC_LIBRARY := jli_static, \
+ OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
+ SRC := $(LIBJLI_SRC_DIRS), \
+ EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
+ EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
+ LANG := C, \
+ OPTIMIZATION := HIGH, \
+ CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
+ ARFLAGS := $(ARFLAGS), \
+ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
TARGETS += $(BUILD_LIBJLI_STATIC)
diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk
index 046bd2ea946..3950b4a7474 100644
--- a/jdk/make/lib/Lib-jdk.attach.gmk
+++ b/jdk/make/lib/Lib-jdk.attach.gmk
@@ -31,7 +31,7 @@ include LibCommon.gmk
$(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
LIBRARY := attach, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \
+ SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
diff --git a/jdk/make/lib/Lib-jdk.security.auth.gmk b/jdk/make/lib/Lib-jdk.security.auth.gmk
index cab72eb3918..80f05da0298 100644
--- a/jdk/make/lib/Lib-jdk.security.auth.gmk
+++ b/jdk/make/lib/Lib-jdk.security.auth.gmk
@@ -28,9 +28,7 @@ include LibCommon.gmk
################################################################################
LIBJAAS_MAPFILE :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
- LIBJAAS_EXCLUDE_FILES := Solaris.c
-else
+ifeq ($(OPENJDK_TARGET_OS), solaris)
# only on solaris...wonder why
LIBJAAS_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjaas/mapfile-vers
endif
@@ -43,7 +41,7 @@ endif
$(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
LIBRARY := $(LIBJAAS_NAME), \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
- SRC := $(JDK_TOPDIR)/src/jdk.security.auth/$(OPENJDK_TARGET_OS_TYPE)/native/libjaas, \
+ SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \
@@ -53,7 +51,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
LDFLAGS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib, \
LDFLAGS_SUFFIX_windows := $(LDFLAGS_JDKLIB_SUFFIX), \
LDFLAGS_SUFFIX_solaris := -lc, \
- EXCLUDE_FILES := $(LIBJAAS_EXCLUDE_FILES), \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $(RC_FLAGS) \
-D "JDK_FNAME=$(LIBJAAS_NAME).dll" \
diff --git a/jdk/make/lib/NetworkingLibraries.gmk b/jdk/make/lib/NetworkingLibraries.gmk
index 47d0b67782a..57d86eabfb5 100644
--- a/jdk/make/lib/NetworkingLibraries.gmk
+++ b/jdk/make/lib/NetworkingLibraries.gmk
@@ -23,39 +23,16 @@
# questions.
#
-LIBNET_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libnet \
- $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnet
-LIBNET_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
- $(LIBJAVA_HEADER_FLAGS)
-
-LIBNET_CFLAGS += $(foreach dir, $(LIBNET_SRC_DIRS), -I$(dir))
-
-LIBNET_EXCLUDE_FILES :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
- LIBNET_EXCLUDE_FILES += solaris_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), linux)
- LIBNET_EXCLUDE_FILES += linux_close.c
-endif
-
-ifneq ($(OPENJDK_TARGET_OS), macosx)
- LIBNET_EXCLUDE_FILES += bsd_close.c
-endif
-
-ifeq ($(OPENJDK_TARGET_OS), aix)
- LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/
-endif
+LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net)
$(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
LIBRARY := net, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(LIBNET_SRC_DIRS), \
- EXCLUDE_FILES := $(LIBNET_EXCLUDE_FILES), \
LANG := C, \
OPTIMIZATION := LOW, \
- CFLAGS := $(CFLAGS_JDKLIB) \
- $(LIBNET_CFLAGS), \
+ CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
+ $(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk
index aaf798cf2fc..9a6e3e07ced 100644
--- a/jdk/make/lib/NioLibraries.gmk
+++ b/jdk/make/lib/NioLibraries.gmk
@@ -65,7 +65,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
SRC := $(BUILD_LIBNIO_SRC), \
EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
- EXCLUDES := sctp, \
LANG := C, \
OPTIMIZATION := HIGH, \
CFLAGS := $(CFLAGS_JDKLIB) \
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index a91eb85fe9d..df91f947ad8 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -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
@@ -214,10 +214,10 @@ SUNWprivate_1.1 {
Java_java_lang_Throwable_fillInStackTrace;
Java_java_lang_Throwable_getStackTraceDepth;
Java_java_lang_Throwable_getStackTraceElement;
- Java_java_lang_UNIXProcess_init;
- Java_java_lang_UNIXProcess_waitForProcessExit;
- Java_java_lang_UNIXProcess_forkAndExec;
- Java_java_lang_UNIXProcess_destroyProcess;
+ Java_java_lang_ProcessImpl_init;
+ Java_java_lang_ProcessImpl_waitForProcessExit;
+ Java_java_lang_ProcessImpl_forkAndExec;
+ Java_java_lang_ProcessImpl_destroyProcess;
Java_java_nio_Bits_copyFromShortArray;
Java_java_nio_Bits_copyToShortArray;
Java_java_nio_Bits_copyFromIntArray;
diff --git a/jdk/make/src/classes/build/tools/deps/CheckDeps.java b/jdk/make/src/classes/build/tools/deps/CheckDeps.java
deleted file mode 100644
index 347a2b212e6..00000000000
--- a/jdk/make/src/classes/build/tools/deps/CheckDeps.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.deps;
-
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.charset.StandardCharsets;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.classfile.Dependencies;
-import com.sun.tools.classfile.Dependency;
-
-/**
- * A simple tool to check the JAR files in a JRE image to ensure that there
- * aren't any references to types that do not exist. The tool is intended to
- * be used in the JDK "profiles" build to help ensure that the profile
- * definitions are kept up to date.
- */
-
-public class CheckDeps {
-
- // classfile API for finding dependencies
- static final Dependency.Finder finder = Dependencies.getClassDependencyFinder();
-
- // "known types", found in rt.jar or other JAR files
- static final Set knownTypes = new HashSet<>();
-
- // References to unknown types. The map key is the unknown type, the
- // map value is the set of classes that reference it.
- static final Map> unknownRefs = new HashMap<>();
-
- // The property name is the name of an unknown type that is allowed to be
- // references. The property value is a comma separated list of the types
- // that are allowed to reference it. The list also includes the names of
- // the profiles that the reference is allowed.
- static final Properties allowedBadRefs = new Properties();
-
- /**
- * Returns the class name for the given class file. In the case of inner
- * classes then the enclosing class is returned in order to keep the
- * rules simple.
- */
- static String toClassName(String s) {
- int i = s.indexOf('$');
- if (i > 0)
- s = s.substring(0, i);
- return s.replace("/", ".");
- }
-
- /**
- * Analyze the dependencies of all classes in the given JAR file. The
- * method updates knownTypes and unknownRefs as part of the analysis.
- */
- static void analyzeDependencies(Path jarpath) throws Exception {
- System.out.format("Analyzing %s%n", jarpath);
- try (JarFile jf = new JarFile(jarpath.toFile())) {
- Enumeration entries = jf.entries();
- while (entries.hasMoreElements()) {
- JarEntry e = entries.nextElement();
- String name = e.getName();
- if (name.endsWith(".class")) {
- ClassFile cf = ClassFile.read(jf.getInputStream(e));
- for (Dependency d : finder.findDependencies(cf)) {
- String origin = toClassName(d.getOrigin().getName());
- String target = toClassName(d.getTarget().getName());
-
- // origin is now known
- unknownRefs.remove(origin);
- knownTypes.add(origin);
-
- // if the target is not known then record the reference
- if (!knownTypes.contains(target)) {
- Set refs = unknownRefs.get(target);
- if (refs == null) {
- // first time seeing this unknown type
- refs = new HashSet<>();
- unknownRefs.put(target, refs);
- }
- refs.add(origin);
- }
- }
- }
- }
- }
- }
-
- /**
- * We have closure (no references to types that do not exist) if
- * unknownRefs is empty. When unknownRefs is not empty then it should
- * only contain references that are allowed to be present (these are
- * loaded from the refs.allowed properties file).
- *
- * @param the profile that is being tested, this determines the exceptions
- * in {@code allowedBadRefs} that apply.
- *
- * @return {@code true} if there are no missing types or the only references
- * to missing types are described by {@code allowedBadRefs}.
- */
- static boolean checkClosure(String profile) {
- // process the references to types that do not exist.
- boolean fail = false;
- for (Map.Entry> entry: unknownRefs.entrySet()) {
- String target = entry.getKey();
- for (String origin: entry.getValue()) {
- // check if origin -> target allowed
- String value = allowedBadRefs.getProperty(target);
- if (value == null) {
- System.err.format("%s -> %s (unknown type)%n", origin, target);
- fail = true;
- } else {
- // target is known, check if the origin is one that we
- // expect and that the exception applies to the profile.
- boolean found = false;
- boolean applicable = false;
- for (String s: value.split(",")) {
- s = s.trim();
- if (s.equals(origin))
- found = true;
- if (s.equals(profile))
- applicable = true;
- }
- if (!found || !applicable) {
- if (!found) {
- System.err.format("%s -> %s (not allowed)%n", origin, target);
- } else {
- System.err.format("%s -> %s (reference not applicable to %s)%n",
- origin, target, profile);
- }
- fail = true;
- }
- }
-
- }
- }
-
- return !fail;
- }
-
- static void fail(URL url) throws Exception {
- System.err.println("One or more unexpected references encountered");
- if (url != null)
- System.err.format("Check %s is up to date%n", Paths.get(url.toURI()));
- System.exit(-1);
- }
-
- public static void main(String[] args) throws Exception {
- // load properties file so that we know what missing types that are
- // allowed to be referenced.
- URL url = CheckDeps.class.getResource("refs.allowed");
- if (url != null) {
- try (InputStream in = url.openStream()) {
- allowedBadRefs.load(new InputStreamReader(in, StandardCharsets.UTF_8));
- }
- }
-
- if (args.length != 2) {
- System.err.println("Usage: java CheckDeps ");
- System.exit(-1);
- }
-
- String image = args[0];
- String profile = args[1];
-
- // process JAR files on boot class path
- Path lib = Paths.get(image, "lib");
- try (DirectoryStream stream = Files.newDirectoryStream(lib, "*.jar")) {
- for (Path jarpath: stream) {
- analyzeDependencies(jarpath);
- }
- }
-
- // classes on boot class path should not reference other types
- boolean okay = checkClosure(profile);
- if (!okay)
- fail(url);
-
- // process JAR files in the extensions directory
- try (DirectoryStream stream = Files.newDirectoryStream(lib.resolve("ext"), "*.jar")) {
- for (Path jarpath: stream) {
- analyzeDependencies(jarpath);
- }
- }
-
- // re-check to ensure that the extensions doesn't reference types that
- // do not exist.
- okay = checkClosure(profile);
- if (!okay)
- fail(url);
- }
-}
diff --git a/jdk/src/java.base/aix/native/libnet/java/net/aix_close.c b/jdk/src/java.base/aix/native/libnet/aix_close.c
similarity index 100%
rename from jdk/src/java.base/aix/native/libnet/java/net/aix_close.c
rename to jdk/src/java.base/aix/native/libnet/aix_close.c
diff --git a/jdk/src/java.base/unix/native/libnet/linux_close.c b/jdk/src/java.base/linux/native/libnet/linux_close.c
similarity index 100%
rename from jdk/src/java.base/unix/native/libnet/linux_close.c
rename to jdk/src/java.base/linux/native/libnet/linux_close.c
diff --git a/jdk/src/java.base/unix/native/libjava/java_props_macosx.c b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.c
similarity index 100%
rename from jdk/src/java.base/unix/native/libjava/java_props_macosx.c
rename to jdk/src/java.base/macosx/native/libjava/java_props_macosx.c
diff --git a/jdk/src/java.base/unix/native/libjava/java_props_macosx.h b/jdk/src/java.base/macosx/native/libjava/java_props_macosx.h
similarity index 100%
rename from jdk/src/java.base/unix/native/libjava/java_props_macosx.h
rename to jdk/src/java.base/macosx/native/libjava/java_props_macosx.h
diff --git a/jdk/src/java.base/unix/native/libnet/bsd_close.c b/jdk/src/java.base/macosx/native/libnet/bsd_close.c
similarity index 100%
rename from jdk/src/java.base/unix/native/libnet/bsd_close.c
rename to jdk/src/java.base/macosx/native/libnet/bsd_close.c
diff --git a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
index 97713d31554..93b1093df7b 100644
--- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
+++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java
@@ -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
@@ -27,6 +27,9 @@ package java.lang;
import sun.misc.FloatingDecimal;
import java.util.Arrays;
+import java.util.Spliterator;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
/**
* A mutable sequence of characters.
@@ -292,7 +295,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
throw new IndexOutOfBoundsException();
}
- return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
+ return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
}
/**
@@ -1431,6 +1434,34 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
@Override
public abstract String toString();
+ /**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public IntStream chars() {
+ // Reuse String-based spliterator. This requires a supplier to
+ // capture the value and count when the terminal operation is executed
+ return StreamSupport.intStream(
+ () -> new String.IntCharArraySpliterator(value, 0, count, 0),
+ Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
+ false);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @since 1.9
+ */
+ @Override
+ public IntStream codePoints() {
+ // Reuse String-based spliterator. This requires a supplier to
+ // capture the value and count when the terminal operation is executed
+ return StreamSupport.intStream(
+ () -> new String.CodePointsSpliterator(value, 0, count, 0),
+ Spliterator.ORDERED,
+ false);
+ }
+
/**
* Needed by {@code String} for the contentEquals method.
*/
diff --git a/jdk/src/java.base/share/classes/java/lang/Object.java b/jdk/src/java.base/share/classes/java/lang/Object.java
index 04ca33153d6..2eeac24a688 100644
--- a/jdk/src/java.base/share/classes/java/lang/Object.java
+++ b/jdk/src/java.base/share/classes/java/lang/Object.java
@@ -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
@@ -41,6 +41,11 @@ public class Object {
registerNatives();
}
+ /**
+ * 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
@@ -86,12 +91,11 @@ public class Object {
* for unequal objects may improve the performance of hash tables.
*
*
- * 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 @@ public class Object {
* ... // Perform action appropriate to condition
* }
*
- * (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).
*
*
If the current thread is {@linkplain java.lang.Thread#interrupt()
* interrupted} by any thread before or while it is waiting, then an
diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java
index 9ff32f48a60..bd39fa60f94 100644
--- a/jdk/src/java.base/share/classes/java/lang/String.java
+++ b/jdk/src/java.base/share/classes/java/lang/String.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2014, 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
@@ -34,10 +34,14 @@ import java.util.Comparator;
import java.util.Formatter;
import java.util.Locale;
import java.util.Objects;
+import java.util.Spliterator;
import java.util.StringJoiner;
+import java.util.function.IntConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import java.util.stream.IntStream;
+import java.util.stream.StreamSupport;
/**
* The {@code String} class represents character strings. All
@@ -2894,6 +2898,180 @@ public final class String
return this;
}
+ static class IntCharArraySpliterator implements Spliterator.OfInt {
+ private final char[] array;
+ private int index; // current index, modified on advance/split
+ private final int fence; // one past last index
+ private final int cs;
+
+ IntCharArraySpliterator(char[] array, int acs) {
+ this(array, 0, array.length, acs);
+ }
+
+ IntCharArraySpliterator(char[] array, int origin, int fence, int acs) {
+ this.array = array;
+ this.index = origin;
+ this.fence = fence;
+ this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
+ | Spliterator.SUBSIZED;
+ }
+
+ @Override
+ public OfInt trySplit() {
+ int lo = index, mid = (lo + fence) >>> 1;
+ return (lo >= mid)
+ ? null
+ : new IntCharArraySpliterator(array, lo, index = mid, cs);
+ }
+
+ @Override
+ public void forEachRemaining(IntConsumer action) {
+ char[] a; int i, hi; // hoist accesses and checks from loop
+ if (action == null)
+ throw new NullPointerException();
+ if ((a = array).length >= (hi = fence) &&
+ (i = index) >= 0 && i < (index = hi)) {
+ do { action.accept(a[i]); } while (++i < hi);
+ }
+ }
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ if (action == null)
+ throw new NullPointerException();
+ if (index >= 0 && index < fence) {
+ action.accept(array[index++]);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public long estimateSize() { return (long)(fence - index); }
+
+ @Override
+ public int characteristics() {
+ return cs;
+ }
+ }
+
+ /**
+ * Returns a stream of {@code int} zero-extending the {@code char} values
+ * from this sequence. Any char which maps to a surrogate code
+ * point is passed through uninterpreted.
+ *
+ * @return an IntStream of char values from this sequence
+ * @since 1.9
+ */
+ @Override
+ public IntStream chars() {
+ return StreamSupport.intStream(
+ new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
+ }
+
+ static class CodePointsSpliterator implements Spliterator.OfInt {
+ private final char[] array;
+ private int index; // current index, modified on advance/split
+ private final int fence; // one past last index
+ private final int cs;
+
+ CodePointsSpliterator(char[] array, int acs) {
+ this(array, 0, array.length, acs);
+ }
+
+ CodePointsSpliterator(char[] array, int origin, int fence, int acs) {
+ this.array = array;
+ this.index = origin;
+ this.fence = fence;
+ this.cs = acs | Spliterator.ORDERED;
+ }
+
+ @Override
+ public OfInt trySplit() {
+ int lo = index, mid = (lo + fence) >>> 1;
+ if (lo >= mid)
+ return null;
+
+ int midOneLess;
+ // If the mid-point intersects a surrogate pair
+ if (Character.isLowSurrogate(array[mid]) &&
+ Character.isHighSurrogate(array[midOneLess = (mid -1)])) {
+ // If there is only one pair it cannot be split
+ if (lo >= midOneLess)
+ return null;
+ // Shift the mid-point to align with the surrogate pair
+ return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
+ }
+ return new CodePointsSpliterator(array, lo, index = mid, cs);
+ }
+
+ @Override
+ public void forEachRemaining(IntConsumer action) {
+ char[] a; int i, hi; // hoist accesses and checks from loop
+ if (action == null)
+ throw new NullPointerException();
+ if ((a = array).length >= (hi = fence) &&
+ (i = index) >= 0 && i < (index = hi)) {
+ do {
+ i = advance(a, i, hi, action);
+ } while (i < hi);
+ }
+ }
+
+ @Override
+ public boolean tryAdvance(IntConsumer action) {
+ if (action == null)
+ throw new NullPointerException();
+ if (index >= 0 && index < fence) {
+ index = advance(array, index, fence, action);
+ return true;
+ }
+ return false;
+ }
+
+ // Advance one code point from the index, i, and return the next
+ // index to advance from
+ private static int advance(char[] a, int i, int hi, IntConsumer action) {
+ char c1 = a[i++];
+ int cp = c1;
+ if (Character.isHighSurrogate(c1) && i < hi) {
+ char c2 = a[i];
+ if (Character.isLowSurrogate(c2)) {
+ i++;
+ cp = Character.toCodePoint(c1, c2);
+ }
+ }
+ action.accept(cp);
+ return i;
+ }
+
+ @Override
+ public long estimateSize() { return (long)(fence - index); }
+
+ @Override
+ public int characteristics() {
+ return cs;
+ }
+ }
+
+ /**
+ * Returns a stream of code point values from this sequence. Any surrogate
+ * pairs encountered in the sequence are combined as if by {@linkplain
+ * Character#toCodePoint Character.toCodePoint} and the result is passed
+ * to the stream. Any other code units, including ordinary BMP characters,
+ * unpaired surrogates, and undefined code units, are zero-extended to
+ * {@code int} values which are then passed to the stream.
+ *
+ * @return an IntStream of Unicode code points from this sequence
+ * @since 1.9
+ */
+ @Override
+ public IntStream codePoints() {
+ return StreamSupport.intStream(
+ new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
+ }
+
/**
* Converts this string to a new character array.
*
diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java
index 1871774a022..ee6588491f9 100644
--- a/jdk/src/java.base/share/classes/java/lang/System.java
+++ b/jdk/src/java.base/share/classes/java/lang/System.java
@@ -376,19 +376,16 @@ public final class System {
* the difference between two such values, obtained within the same
* instance of a Java virtual machine, is computed.
*
- *
For example, to measure how long some code takes to execute:
- *
{@code
+ *
For example, to measure how long some code takes to execute:
+ *
{@code
* long startTime = System.nanoTime();
* // ... the code being measured ...
- * long estimatedTime = System.nanoTime() - startTime;}
+ * long elapsedNanos = System.nanoTime() - startTime;}
*
- *
To compare two nanoTime values
- *
{@code
- * long t0 = System.nanoTime();
- * ...
- * long t1 = System.nanoTime();}
- *
- * one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
+ *
To compare elapsed time against a timeout, use
{@code
+ * if (System.nanoTime() - startTime >= timeoutNanos) ...}
+ * instead of
{@code
+ * if (System.nanoTime() >= startTime + timeoutNanos) ...}
* because of the possibility of numerical overflow.
*
* @return the current value of the running Java Virtual Machine's
diff --git a/jdk/src/java.base/share/classes/java/util/Spliterator.java b/jdk/src/java.base/share/classes/java/util/Spliterator.java
index 324f9e0356c..96db12f0d60 100644
--- a/jdk/src/java.base/share/classes/java/util/Spliterator.java
+++ b/jdk/src/java.base/share/classes/java/util/Spliterator.java
@@ -553,6 +553,12 @@ public interface Spliterator {
* sub-split size is known and additions or removals to the source are not
* reflected when traversing.
*
+ *
A top-level Spliterator should not report both {@code CONCURRENT} and
+ * {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
+ * is inconsistent and no guarantees can be made about any computation using
+ * that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
+ * additions or removals to the source are not reflected when traversing.
+ *
* @apiNote Most concurrent collections maintain a consistency policy
* guaranteeing accuracy with respect to elements present at the point of
* Spliterator construction, but possibly not reflecting subsequent
diff --git a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java
index 08d04fde377..46080c3bd22 100644
--- a/jdk/src/java.base/share/classes/sun/misc/Unsafe.java
+++ b/jdk/src/java.base/share/classes/sun/misc/Unsafe.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2013, 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
@@ -845,22 +845,6 @@ public final class Unsafe {
public native Object allocateInstance(Class> cls)
throws InstantiationException;
- /** Lock the object. It must get unlocked via {@link #monitorExit}. */
- public native void monitorEnter(Object o);
-
- /**
- * Unlock the object. It must have been locked via {@link
- * #monitorEnter}.
- */
- public native void monitorExit(Object o);
-
- /**
- * Tries to lock the object. Returns true or false to indicate
- * whether the lock succeeded. If it did, the object must be
- * unlocked via {@link #monitorExit}.
- */
- public native boolean tryMonitorEnter(Object o);
-
/** Throw the exception without telling the verifier. */
public native void throwException(Throwable ee);
diff --git a/jdk/src/java.base/unix/native/libnet/solaris_close.c b/jdk/src/java.base/solaris/native/libnet/solaris_close.c
similarity index 100%
rename from jdk/src/java.base/unix/native/libnet/solaris_close.c
rename to jdk/src/java.base/solaris/native/libnet/solaris_close.c
diff --git a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java
index 777018bddb0..a35405fc8d9 100644
--- a/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java
+++ b/jdk/src/java.base/unix/classes/java/lang/ProcessImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, 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,24 +25,156 @@
package java.lang;
-import java.io.IOException;
+import java.lang.ProcessBuilder.Redirect;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
-import java.lang.ProcessBuilder.Redirect;
-import java.lang.ProcessBuilder.Redirect;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+import java.security.AccessController;
+import static java.security.AccessController.doPrivileged;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
/**
- * This class is for the exclusive use of ProcessBuilder.start() to
- * create new processes.
+ * This java.lang.Process subclass in the UNIX environment is for the exclusive use of
+ * ProcessBuilder.start() to create new processes.
*
+ * @author Mario Wolczko and Ross Knippel.
+ * @author Konstantin Kladko (ported to Linux and Bsd)
* @author Martin Buchholz
+ * @author Volker Simonis (ported to AIX)
* @since 1.5
*/
-final class ProcessImpl {
+final class ProcessImpl extends Process {
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
- private ProcessImpl() {} // Not instantiable
+ private final int pid;
+ private int exitcode;
+ private boolean hasExited;
+
+ private /* final */ OutputStream stdin;
+ private /* final */ InputStream stdout;
+ private /* final */ InputStream stderr;
+
+ // only used on Solaris
+ private /* final */ DeferredCloseInputStream stdout_inner_stream;
+
+ private static enum LaunchMechanism {
+ // order IS important!
+ FORK,
+ POSIX_SPAWN,
+ VFORK
+ }
+
+ private static enum Platform {
+
+ LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
+
+ BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+ SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
+
+ AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
+
+ final LaunchMechanism defaultLaunchMechanism;
+ final Set validLaunchMechanisms;
+
+ Platform(LaunchMechanism ... launchMechanisms) {
+ this.defaultLaunchMechanism = launchMechanisms[0];
+ this.validLaunchMechanisms =
+ EnumSet.copyOf(Arrays.asList(launchMechanisms));
+ }
+
+ @SuppressWarnings("fallthrough")
+ private String helperPath(String javahome, String osArch) {
+ switch (this) {
+ case SOLARIS:
+ if (osArch.equals("x86")) { osArch = "i386"; }
+ else if (osArch.equals("x86_64")) { osArch = "amd64"; }
+ // fall through...
+ case LINUX:
+ case AIX:
+ return javahome + "/lib/" + osArch + "/jspawnhelper";
+
+ case BSD:
+ return javahome + "/lib/jspawnhelper";
+
+ default:
+ throw new AssertionError("Unsupported platform: " + this);
+ }
+ }
+
+ String helperPath() {
+ return AccessController.doPrivileged(
+ (PrivilegedAction) () ->
+ helperPath(System.getProperty("java.home"),
+ System.getProperty("os.arch"))
+ );
+ }
+
+ LaunchMechanism launchMechanism() {
+ return AccessController.doPrivileged(
+ (PrivilegedAction) () -> {
+ String s = System.getProperty(
+ "jdk.lang.Process.launchMechanism");
+ LaunchMechanism lm;
+ if (s == null) {
+ lm = defaultLaunchMechanism;
+ s = lm.name().toLowerCase(Locale.ENGLISH);
+ } else {
+ try {
+ lm = LaunchMechanism.valueOf(
+ s.toUpperCase(Locale.ENGLISH));
+ } catch (IllegalArgumentException e) {
+ lm = null;
+ }
+ }
+ if (lm == null || !validLaunchMechanisms.contains(lm)) {
+ throw new Error(
+ s + " is not a supported " +
+ "process launch mechanism on this platform."
+ );
+ }
+ return lm;
+ }
+ );
+ }
+
+ static Platform get() {
+ String osName = AccessController.doPrivileged(
+ (PrivilegedAction) () -> System.getProperty("os.name")
+ );
+
+ if (osName.equals("Linux")) { return LINUX; }
+ if (osName.contains("OS X")) { return BSD; }
+ if (osName.equals("SunOS")) { return SOLARIS; }
+ if (osName.equals("AIX")) { return AIX; }
+
+ throw new Error(osName + " is not a supported OS platform.");
+ }
+ }
+
+ private static final Platform platform = Platform.get();
+ private static final LaunchMechanism launchMechanism = platform.launchMechanism();
+ private static final byte[] helperpath = toCString(platform.helperPath());
+
+ /* this is for the reaping thread */
+ private native int waitForProcessExit(int pid);
private static byte[] toCString(String s) {
if (s == null)
@@ -50,8 +182,8 @@ final class ProcessImpl {
byte[] bytes = s.getBytes();
byte[] result = new byte[bytes.length + 1];
System.arraycopy(bytes, 0,
- result, 0,
- bytes.length);
+ result, 0,
+ bytes.length);
result[result.length-1] = (byte)0;
return result;
}
@@ -62,7 +194,7 @@ final class ProcessImpl {
String dir,
ProcessBuilder.Redirect[] redirects,
boolean redirectErrorStream)
- throws IOException
+ throws IOException
{
assert cmdarray != null && cmdarray.length > 0;
@@ -112,7 +244,7 @@ final class ProcessImpl {
std_fds[1] = 1;
else {
f1 = new FileOutputStream(redirects[1].file(),
- redirects[1].append());
+ redirects[1].append());
std_fds[1] = fdAccess.get(f1.getFD());
}
@@ -122,18 +254,18 @@ final class ProcessImpl {
std_fds[2] = 2;
else {
f2 = new FileOutputStream(redirects[2].file(),
- redirects[2].append());
+ redirects[2].append());
std_fds[2] = fdAccess.get(f2.getFD());
}
}
- return new UNIXProcess
- (toCString(cmdarray[0]),
- argBlock, args.length,
- envBlock, envc[0],
- toCString(dir),
- std_fds,
- redirectErrorStream);
+ return new ProcessImpl
+ (toCString(cmdarray[0]),
+ argBlock, args.length,
+ envBlock, envc[0],
+ toCString(dir),
+ std_fds,
+ redirectErrorStream);
} finally {
// In theory, close() can throw IOException
// (although it is rather unlikely to happen here)
@@ -144,4 +276,654 @@ final class ProcessImpl {
}
}
}
+
+
+ /**
+ * Creates a process. Depending on the {@code mode} flag, this is done by
+ * one of the following mechanisms:
+ *
+ * 1 - fork(2) and exec(2)
+ * 2 - posix_spawn(3P)
+ * 3 - vfork(2) and exec(2)
+ *
+ * (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
+ *
+ * @param fds an array of three file descriptors.
+ * Indexes 0, 1, and 2 correspond to standard input,
+ * standard output and standard error, respectively. On
+ * input, a value of -1 means to create a pipe to connect
+ * child and parent processes. On output, a value which
+ * is not -1 is the parent pipe fd corresponding to the
+ * pipe which has been created. An element of this array
+ * is -1 on input if and only if it is not -1 on
+ * output.
+ * @return the pid of the subprocess
+ */
+ private native int forkAndExec(int mode, byte[] helperpath,
+ byte[] prog,
+ byte[] argBlock, int argc,
+ byte[] envBlock, int envc,
+ byte[] dir,
+ int[] fds,
+ boolean redirectErrorStream)
+ throws IOException;
+
+ /**
+ * The thread pool of "process reaper" daemon threads.
+ */
+ private static final Executor processReaperExecutor =
+ doPrivileged((PrivilegedAction) () -> {
+
+ ThreadGroup tg = Thread.currentThread().getThreadGroup();
+ while (tg.getParent() != null) tg = tg.getParent();
+ ThreadGroup systemThreadGroup = tg;
+
+ ThreadFactory threadFactory = grimReaper -> {
+ // Our thread stack requirement is quite modest.
+ Thread t = new Thread(systemThreadGroup, grimReaper,
+ "process reaper", 32768);
+ t.setDaemon(true);
+ // A small attempt (probably futile) to avoid priority inversion
+ t.setPriority(Thread.MAX_PRIORITY);
+ return t;
+ };
+
+ return Executors.newCachedThreadPool(threadFactory);
+ });
+
+ private ProcessImpl(final byte[] prog,
+ final byte[] argBlock, final int argc,
+ final byte[] envBlock, final int envc,
+ final byte[] dir,
+ final int[] fds,
+ final boolean redirectErrorStream)
+ throws IOException {
+
+ pid = forkAndExec(launchMechanism.ordinal() + 1,
+ helperpath,
+ prog,
+ argBlock, argc,
+ envBlock, envc,
+ dir,
+ fds,
+ redirectErrorStream);
+
+ try {
+ doPrivileged((PrivilegedExceptionAction) () -> {
+ initStreams(fds);
+ return null;
+ });
+ } catch (PrivilegedActionException ex) {
+ throw (IOException) ex.getException();
+ }
+ }
+
+ static FileDescriptor newFileDescriptor(int fd) {
+ FileDescriptor fileDescriptor = new FileDescriptor();
+ fdAccess.set(fileDescriptor, fd);
+ return fileDescriptor;
+ }
+
+ void initStreams(int[] fds) throws IOException {
+ switch (platform) {
+ case LINUX:
+ case BSD:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new ProcessPipeOutputStream(fds[0]);
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ProcessPipeInputStream(fds[1]);
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ProcessPipeInputStream(fds[2]);
+
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+
+ if (stdout instanceof ProcessPipeInputStream)
+ ((ProcessPipeInputStream) stdout).processExited();
+
+ if (stderr instanceof ProcessPipeInputStream)
+ ((ProcessPipeInputStream) stderr).processExited();
+
+ if (stdin instanceof ProcessPipeOutputStream)
+ ((ProcessPipeOutputStream) stdin).processExited();
+ });
+ break;
+
+ case SOLARIS:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new BufferedOutputStream(
+ new FileOutputStream(newFileDescriptor(fds[0])));
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new BufferedInputStream(
+ stdout_inner_stream =
+ new DeferredCloseInputStream(
+ newFileDescriptor(fds[1])));
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseInputStream(newFileDescriptor(fds[2]));
+
+ /*
+ * For each subprocess forked a corresponding reaper task
+ * is submitted. That task is the only thread which waits
+ * for the subprocess to terminate and it doesn't hold any
+ * locks while doing so. This design allows waitFor() and
+ * exitStatus() to be safely executed in parallel (and they
+ * need no native code).
+ */
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+ });
+ break;
+
+ case AIX:
+ stdin = (fds[0] == -1) ?
+ ProcessBuilder.NullOutputStream.INSTANCE :
+ new ProcessPipeOutputStream(fds[0]);
+
+ stdout = (fds[1] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseProcessPipeInputStream(fds[1]);
+
+ stderr = (fds[2] == -1) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new DeferredCloseProcessPipeInputStream(fds[2]);
+
+ processReaperExecutor.execute(() -> {
+ int exitcode = waitForProcessExit(pid);
+
+ synchronized (this) {
+ this.exitcode = exitcode;
+ this.hasExited = true;
+ this.notifyAll();
+ }
+
+ if (stdout instanceof DeferredCloseProcessPipeInputStream)
+ ((DeferredCloseProcessPipeInputStream) stdout).processExited();
+
+ if (stderr instanceof DeferredCloseProcessPipeInputStream)
+ ((DeferredCloseProcessPipeInputStream) stderr).processExited();
+
+ if (stdin instanceof ProcessPipeOutputStream)
+ ((ProcessPipeOutputStream) stdin).processExited();
+ });
+ break;
+
+ default: throw new AssertionError("Unsupported platform: " + platform);
+ }
+ }
+
+ public OutputStream getOutputStream() {
+ return stdin;
+ }
+
+ public InputStream getInputStream() {
+ return stdout;
+ }
+
+ public InputStream getErrorStream() {
+ return stderr;
+ }
+
+ public synchronized int waitFor() throws InterruptedException {
+ while (!hasExited) {
+ wait();
+ }
+ return exitcode;
+ }
+
+ @Override
+ public synchronized boolean waitFor(long timeout, TimeUnit unit)
+ throws InterruptedException
+ {
+ if (hasExited) return true;
+ if (timeout <= 0) return false;
+
+ long remainingNanos = unit.toNanos(timeout);
+ long deadline = System.nanoTime() + remainingNanos;
+
+ do {
+ // Round up to next millisecond
+ wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
+ if (hasExited) {
+ return true;
+ }
+ remainingNanos = deadline - System.nanoTime();
+ } while (remainingNanos > 0);
+ return hasExited;
+ }
+
+ public synchronized int exitValue() {
+ if (!hasExited) {
+ throw new IllegalThreadStateException("process hasn't exited");
+ }
+ return exitcode;
+ }
+
+ private static native void destroyProcess(int pid, boolean force);
+
+ private void destroy(boolean force) {
+ switch (platform) {
+ case LINUX:
+ case BSD:
+ case AIX:
+ // There is a risk that pid will be recycled, causing us to
+ // kill the wrong process! So we only terminate processes
+ // that appear to still be running. Even with this check,
+ // there is an unavoidable race condition here, but the window
+ // is very small, and OSes try hard to not recycle pids too
+ // soon, so this is quite safe.
+ synchronized (this) {
+ if (!hasExited)
+ destroyProcess(pid, force);
+ }
+ try { stdin.close(); } catch (IOException ignored) {}
+ try { stdout.close(); } catch (IOException ignored) {}
+ try { stderr.close(); } catch (IOException ignored) {}
+ break;
+
+ case SOLARIS:
+ // There is a risk that pid will be recycled, causing us to
+ // kill the wrong process! So we only terminate processes
+ // that appear to still be running. Even with this check,
+ // there is an unavoidable race condition here, but the window
+ // is very small, and OSes try hard to not recycle pids too
+ // soon, so this is quite safe.
+ synchronized (this) {
+ if (!hasExited)
+ destroyProcess(pid, force);
+ try {
+ stdin.close();
+ if (stdout_inner_stream != null)
+ stdout_inner_stream.closeDeferred(stdout);
+ if (stderr instanceof DeferredCloseInputStream)
+ ((DeferredCloseInputStream) stderr)
+ .closeDeferred(stderr);
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ break;
+
+ default: throw new AssertionError("Unsupported platform: " + platform);
+ }
+ }
+
+ public void destroy() {
+ destroy(false);
+ }
+
+ @Override
+ public Process destroyForcibly() {
+ destroy(true);
+ return this;
+ }
+
+ @Override
+ public long getPid() {
+ return pid;
+ }
+
+ @Override
+ public synchronized boolean isAlive() {
+ return !hasExited;
+ }
+
+ private static native void init();
+
+ static {
+ init();
+ }
+
+ /**
+ * A buffered input stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ *
+ * This is tricky because we do not want the user-level InputStream to be
+ * closed until the user invokes close(), and we need to continue to be
+ * able to read any buffered data lingering in the OS pipe buffer.
+ */
+ private static class ProcessPipeInputStream extends BufferedInputStream {
+ private final Object closeLock = new Object();
+
+ ProcessPipeInputStream(int fd) {
+ super(new FileInputStream(newFileDescriptor(fd)));
+ }
+ private static byte[] drainInputStream(InputStream in)
+ throws IOException {
+ int n = 0;
+ int j;
+ byte[] a = null;
+ while ((j = in.available()) > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ n += in.read(a, n, j);
+ }
+ return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ synchronized (closeLock) {
+ try {
+ InputStream in = this.in;
+ // this stream is closed if and only if: in == null
+ if (in != null) {
+ byte[] stragglers = drainInputStream(in);
+ in.close();
+ this.in = (stragglers == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(stragglers);
+ }
+ } catch (IOException ignored) {}
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other
+ // methods. Synchronizing helps avoid race with processExited().
+ synchronized (closeLock) {
+ super.close();
+ }
+ }
+ }
+
+ /**
+ * A buffered output stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ */
+ private static class ProcessPipeOutputStream extends BufferedOutputStream {
+ ProcessPipeOutputStream(int fd) {
+ super(new FileOutputStream(newFileDescriptor(fd)));
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ OutputStream out = this.out;
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException ignored) {
+ // We know of no reason to get an IOException, but if
+ // we do, there's nothing else to do but carry on.
+ }
+ this.out = ProcessBuilder.NullOutputStream.INSTANCE;
+ }
+ }
+ }
+
+ // A FileInputStream that supports the deferment of the actual close
+ // operation until the last pending I/O operation on the stream has
+ // finished. This is required on Solaris because we must close the stdin
+ // and stdout streams in the destroy method in order to reclaim the
+ // underlying file descriptors. Doing so, however, causes any thread
+ // currently blocked in a read on one of those streams to receive an
+ // IOException("Bad file number"), which is incompatible with historical
+ // behavior. By deferring the close we allow any pending reads to see -1
+ // (EOF) as they did before.
+ //
+ private static class DeferredCloseInputStream extends FileInputStream
+ {
+ DeferredCloseInputStream(FileDescriptor fd) {
+ super(fd);
+ }
+
+ private Object lock = new Object(); // For the following fields
+ private boolean closePending = false;
+ private int useCount = 0;
+ private InputStream streamToClose;
+
+ private void raise() {
+ synchronized (lock) {
+ useCount++;
+ }
+ }
+
+ private void lower() throws IOException {
+ synchronized (lock) {
+ useCount--;
+ if (useCount == 0 && closePending) {
+ streamToClose.close();
+ }
+ }
+ }
+
+ // stc is the actual stream to be closed; it might be this object, or
+ // it might be an upstream object for which this object is downstream.
+ //
+ private void closeDeferred(InputStream stc) throws IOException {
+ synchronized (lock) {
+ if (useCount == 0) {
+ stc.close();
+ } else {
+ closePending = true;
+ streamToClose = stc;
+ }
+ }
+ }
+
+ public void close() throws IOException {
+ synchronized (lock) {
+ useCount = 0;
+ closePending = false;
+ }
+ super.close();
+ }
+
+ public int read() throws IOException {
+ raise();
+ try {
+ return super.read();
+ } finally {
+ lower();
+ }
+ }
+
+ public int read(byte[] b) throws IOException {
+ raise();
+ try {
+ return super.read(b);
+ } finally {
+ lower();
+ }
+ }
+
+ public int read(byte[] b, int off, int len) throws IOException {
+ raise();
+ try {
+ return super.read(b, off, len);
+ } finally {
+ lower();
+ }
+ }
+
+ public long skip(long n) throws IOException {
+ raise();
+ try {
+ return super.skip(n);
+ } finally {
+ lower();
+ }
+ }
+
+ public int available() throws IOException {
+ raise();
+ try {
+ return super.available();
+ } finally {
+ lower();
+ }
+ }
+ }
+
+ /**
+ * A buffered input stream for a subprocess pipe file descriptor
+ * that allows the underlying file descriptor to be reclaimed when
+ * the process exits, via the processExited hook.
+ *
+ * This is tricky because we do not want the user-level InputStream to be
+ * closed until the user invokes close(), and we need to continue to be
+ * able to read any buffered data lingering in the OS pipe buffer.
+ *
+ * On AIX this is especially tricky, because the 'close()' system call
+ * will block if another thread is at the same time blocked in a file
+ * operation (e.g. 'read()') on the same file descriptor. We therefore
+ * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
+ * with the DeferredCloseInputStream approach used on Solaris. This means
+ * that every potentially blocking operation on the file descriptor
+ * increments a counter before it is executed and decrements it once it
+ * finishes. The 'close()' operation will only be executed if there are
+ * no pending operations. Otherwise it is deferred after the last pending
+ * operation has finished.
+ *
+ */
+ private static class DeferredCloseProcessPipeInputStream
+ extends BufferedInputStream {
+
+ private final Object closeLock = new Object();
+ private int useCount = 0;
+ private boolean closePending = false;
+
+ DeferredCloseProcessPipeInputStream(int fd) {
+ super(new FileInputStream(newFileDescriptor(fd)));
+ }
+
+ private InputStream drainInputStream(InputStream in)
+ throws IOException {
+ int n = 0;
+ int j;
+ byte[] a = null;
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ j = in.available();
+ }
+ while (j > 0) {
+ a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
+ synchronized (closeLock) {
+ if (buf == null) // asynchronous close()?
+ return null; // discard
+ n += in.read(a, n, j);
+ j = in.available();
+ }
+ }
+ return (a == null) ?
+ ProcessBuilder.NullInputStream.INSTANCE :
+ new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
+ }
+
+ /** Called by the process reaper thread when the process exits. */
+ synchronized void processExited() {
+ try {
+ InputStream in = this.in;
+ if (in != null) {
+ InputStream stragglers = drainInputStream(in);
+ in.close();
+ this.in = stragglers;
+ }
+ } catch (IOException ignored) { }
+ }
+
+ private void raise() {
+ synchronized (closeLock) {
+ useCount++;
+ }
+ }
+
+ private void lower() throws IOException {
+ synchronized (closeLock) {
+ useCount--;
+ if (useCount == 0 && closePending) {
+ closePending = false;
+ super.close();
+ }
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ raise();
+ try {
+ return super.read();
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ raise();
+ try {
+ return super.read(b);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ raise();
+ try {
+ return super.read(b, off, len);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public long skip(long n) throws IOException {
+ raise();
+ try {
+ return super.skip(n);
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public int available() throws IOException {
+ raise();
+ try {
+ return super.available();
+ } finally {
+ lower();
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ // BufferedInputStream#close() is not synchronized unlike most other
+ // methods. Synchronizing helps avoid racing with drainInputStream().
+ synchronized (closeLock) {
+ if (useCount == 0) {
+ super.close();
+ }
+ else {
+ closePending = true;
+ }
+ }
+ }
+ }
}
diff --git a/jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java b/jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java
deleted file mode 100644
index d3adac90cd2..00000000000
--- a/jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java
+++ /dev/null
@@ -1,836 +0,0 @@
-/*
- * Copyright (c) 1995, 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 java.lang;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-import java.security.AccessController;
-import static java.security.AccessController.doPrivileged;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-
-/**
- * java.lang.Process subclass in the UNIX environment.
- *
- * @author Mario Wolczko and Ross Knippel.
- * @author Konstantin Kladko (ported to Linux and Bsd)
- * @author Martin Buchholz
- * @author Volker Simonis (ported to AIX)
- */
-final class UNIXProcess extends Process {
- private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
- = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
-
- private final int pid;
- private int exitcode;
- private boolean hasExited;
-
- private /* final */ OutputStream stdin;
- private /* final */ InputStream stdout;
- private /* final */ InputStream stderr;
-
- // only used on Solaris
- private /* final */ DeferredCloseInputStream stdout_inner_stream;
-
- private static enum LaunchMechanism {
- // order IS important!
- FORK,
- POSIX_SPAWN,
- VFORK
- }
-
- private static enum Platform {
-
- LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
-
- BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
- SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
-
- AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
-
- final LaunchMechanism defaultLaunchMechanism;
- final Set validLaunchMechanisms;
-
- Platform(LaunchMechanism ... launchMechanisms) {
- this.defaultLaunchMechanism = launchMechanisms[0];
- this.validLaunchMechanisms =
- EnumSet.copyOf(Arrays.asList(launchMechanisms));
- }
-
- @SuppressWarnings("fallthrough")
- private String helperPath(String javahome, String osArch) {
- switch (this) {
- case SOLARIS:
- if (osArch.equals("x86")) { osArch = "i386"; }
- else if (osArch.equals("x86_64")) { osArch = "amd64"; }
- // fall through...
- case LINUX:
- case AIX:
- return javahome + "/lib/" + osArch + "/jspawnhelper";
-
- case BSD:
- return javahome + "/lib/jspawnhelper";
-
- default:
- throw new AssertionError("Unsupported platform: " + this);
- }
- }
-
- String helperPath() {
- return AccessController.doPrivileged(
- (PrivilegedAction) () ->
- helperPath(System.getProperty("java.home"),
- System.getProperty("os.arch"))
- );
- }
-
- LaunchMechanism launchMechanism() {
- return AccessController.doPrivileged(
- (PrivilegedAction) () -> {
- String s = System.getProperty(
- "jdk.lang.Process.launchMechanism");
- LaunchMechanism lm;
- if (s == null) {
- lm = defaultLaunchMechanism;
- s = lm.name().toLowerCase(Locale.ENGLISH);
- } else {
- try {
- lm = LaunchMechanism.valueOf(
- s.toUpperCase(Locale.ENGLISH));
- } catch (IllegalArgumentException e) {
- lm = null;
- }
- }
- if (lm == null || !validLaunchMechanisms.contains(lm)) {
- throw new Error(
- s + " is not a supported " +
- "process launch mechanism on this platform."
- );
- }
- return lm;
- }
- );
- }
-
- static Platform get() {
- String osName = AccessController.doPrivileged(
- (PrivilegedAction) () -> System.getProperty("os.name")
- );
-
- if (osName.equals("Linux")) { return LINUX; }
- if (osName.contains("OS X")) { return BSD; }
- if (osName.equals("SunOS")) { return SOLARIS; }
- if (osName.equals("AIX")) { return AIX; }
-
- throw new Error(osName + " is not a supported OS platform.");
- }
- }
-
- private static final Platform platform = Platform.get();
- private static final LaunchMechanism launchMechanism = platform.launchMechanism();
- private static final byte[] helperpath = toCString(platform.helperPath());
-
- private static byte[] toCString(String s) {
- if (s == null)
- return null;
- byte[] bytes = s.getBytes();
- byte[] result = new byte[bytes.length + 1];
- System.arraycopy(bytes, 0,
- result, 0,
- bytes.length);
- result[result.length-1] = (byte)0;
- return result;
- }
-
- /* this is for the reaping thread */
- private native int waitForProcessExit(int pid);
-
- /**
- * Creates a process. Depending on the {@code mode} flag, this is done by
- * one of the following mechanisms:
- *
- * 1 - fork(2) and exec(2)
- * 2 - posix_spawn(3P)
- * 3 - vfork(2) and exec(2)
- *
- * (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
- *
- * @param fds an array of three file descriptors.
- * Indexes 0, 1, and 2 correspond to standard input,
- * standard output and standard error, respectively. On
- * input, a value of -1 means to create a pipe to connect
- * child and parent processes. On output, a value which
- * is not -1 is the parent pipe fd corresponding to the
- * pipe which has been created. An element of this array
- * is -1 on input if and only if it is not -1 on
- * output.
- * @return the pid of the subprocess
- */
- private native int forkAndExec(int mode, byte[] helperpath,
- byte[] prog,
- byte[] argBlock, int argc,
- byte[] envBlock, int envc,
- byte[] dir,
- int[] fds,
- boolean redirectErrorStream)
- throws IOException;
-
- /**
- * The thread pool of "process reaper" daemon threads.
- */
- private static final Executor processReaperExecutor =
- doPrivileged((PrivilegedAction) () -> {
-
- ThreadGroup tg = Thread.currentThread().getThreadGroup();
- while (tg.getParent() != null) tg = tg.getParent();
- ThreadGroup systemThreadGroup = tg;
-
- ThreadFactory threadFactory = grimReaper -> {
- // Our thread stack requirement is quite modest.
- Thread t = new Thread(systemThreadGroup, grimReaper,
- "process reaper", 32768);
- t.setDaemon(true);
- // A small attempt (probably futile) to avoid priority inversion
- t.setPriority(Thread.MAX_PRIORITY);
- return t;
- };
-
- return Executors.newCachedThreadPool(threadFactory);
- });
-
- UNIXProcess(final byte[] prog,
- final byte[] argBlock, final int argc,
- final byte[] envBlock, final int envc,
- final byte[] dir,
- final int[] fds,
- final boolean redirectErrorStream)
- throws IOException {
-
- pid = forkAndExec(launchMechanism.ordinal() + 1,
- helperpath,
- prog,
- argBlock, argc,
- envBlock, envc,
- dir,
- fds,
- redirectErrorStream);
-
- try {
- doPrivileged((PrivilegedExceptionAction) () -> {
- initStreams(fds);
- return null;
- });
- } catch (PrivilegedActionException ex) {
- throw (IOException) ex.getException();
- }
- }
-
- static FileDescriptor newFileDescriptor(int fd) {
- FileDescriptor fileDescriptor = new FileDescriptor();
- fdAccess.set(fileDescriptor, fd);
- return fileDescriptor;
- }
-
- void initStreams(int[] fds) throws IOException {
- switch (platform) {
- case LINUX:
- case BSD:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new ProcessPipeOutputStream(fds[0]);
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ProcessPipeInputStream(fds[1]);
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ProcessPipeInputStream(fds[2]);
-
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
-
- if (stdout instanceof ProcessPipeInputStream)
- ((ProcessPipeInputStream) stdout).processExited();
-
- if (stderr instanceof ProcessPipeInputStream)
- ((ProcessPipeInputStream) stderr).processExited();
-
- if (stdin instanceof ProcessPipeOutputStream)
- ((ProcessPipeOutputStream) stdin).processExited();
- });
- break;
-
- case SOLARIS:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new BufferedOutputStream(
- new FileOutputStream(newFileDescriptor(fds[0])));
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new BufferedInputStream(
- stdout_inner_stream =
- new DeferredCloseInputStream(
- newFileDescriptor(fds[1])));
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseInputStream(newFileDescriptor(fds[2]));
-
- /*
- * For each subprocess forked a corresponding reaper task
- * is submitted. That task is the only thread which waits
- * for the subprocess to terminate and it doesn't hold any
- * locks while doing so. This design allows waitFor() and
- * exitStatus() to be safely executed in parallel (and they
- * need no native code).
- */
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
- });
- break;
-
- case AIX:
- stdin = (fds[0] == -1) ?
- ProcessBuilder.NullOutputStream.INSTANCE :
- new ProcessPipeOutputStream(fds[0]);
-
- stdout = (fds[1] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseProcessPipeInputStream(fds[1]);
-
- stderr = (fds[2] == -1) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new DeferredCloseProcessPipeInputStream(fds[2]);
-
- processReaperExecutor.execute(() -> {
- int exitcode = waitForProcessExit(pid);
-
- synchronized (this) {
- this.exitcode = exitcode;
- this.hasExited = true;
- this.notifyAll();
- }
-
- if (stdout instanceof DeferredCloseProcessPipeInputStream)
- ((DeferredCloseProcessPipeInputStream) stdout).processExited();
-
- if (stderr instanceof DeferredCloseProcessPipeInputStream)
- ((DeferredCloseProcessPipeInputStream) stderr).processExited();
-
- if (stdin instanceof ProcessPipeOutputStream)
- ((ProcessPipeOutputStream) stdin).processExited();
- });
- break;
-
- default: throw new AssertionError("Unsupported platform: " + platform);
- }
- }
-
- public OutputStream getOutputStream() {
- return stdin;
- }
-
- public InputStream getInputStream() {
- return stdout;
- }
-
- public InputStream getErrorStream() {
- return stderr;
- }
-
- public synchronized int waitFor() throws InterruptedException {
- while (!hasExited) {
- wait();
- }
- return exitcode;
- }
-
- @Override
- public synchronized boolean waitFor(long timeout, TimeUnit unit)
- throws InterruptedException
- {
- if (hasExited) return true;
- if (timeout <= 0) return false;
-
- long remainingNanos = unit.toNanos(timeout);
- long deadline = System.nanoTime() + remainingNanos;
-
- do {
- // Round up to next millisecond
- wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
- if (hasExited) {
- return true;
- }
- remainingNanos = deadline - System.nanoTime();
- } while (remainingNanos > 0);
- return hasExited;
- }
-
- public synchronized int exitValue() {
- if (!hasExited) {
- throw new IllegalThreadStateException("process hasn't exited");
- }
- return exitcode;
- }
-
- private static native void destroyProcess(int pid, boolean force);
-
- private void destroy(boolean force) {
- switch (platform) {
- case LINUX:
- case BSD:
- case AIX:
- // There is a risk that pid will be recycled, causing us to
- // kill the wrong process! So we only terminate processes
- // that appear to still be running. Even with this check,
- // there is an unavoidable race condition here, but the window
- // is very small, and OSes try hard to not recycle pids too
- // soon, so this is quite safe.
- synchronized (this) {
- if (!hasExited)
- destroyProcess(pid, force);
- }
- try { stdin.close(); } catch (IOException ignored) {}
- try { stdout.close(); } catch (IOException ignored) {}
- try { stderr.close(); } catch (IOException ignored) {}
- break;
-
- case SOLARIS:
- // There is a risk that pid will be recycled, causing us to
- // kill the wrong process! So we only terminate processes
- // that appear to still be running. Even with this check,
- // there is an unavoidable race condition here, but the window
- // is very small, and OSes try hard to not recycle pids too
- // soon, so this is quite safe.
- synchronized (this) {
- if (!hasExited)
- destroyProcess(pid, force);
- try {
- stdin.close();
- if (stdout_inner_stream != null)
- stdout_inner_stream.closeDeferred(stdout);
- if (stderr instanceof DeferredCloseInputStream)
- ((DeferredCloseInputStream) stderr)
- .closeDeferred(stderr);
- } catch (IOException e) {
- // ignore
- }
- }
- break;
-
- default: throw new AssertionError("Unsupported platform: " + platform);
- }
- }
-
- public void destroy() {
- destroy(false);
- }
-
- @Override
- public Process destroyForcibly() {
- destroy(true);
- return this;
- }
-
- @Override
- public long getPid() {
- return pid;
- }
-
- @Override
- public synchronized boolean isAlive() {
- return !hasExited;
- }
-
- private static native void init();
-
- static {
- init();
- }
-
- /**
- * A buffered input stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- *
- * This is tricky because we do not want the user-level InputStream to be
- * closed until the user invokes close(), and we need to continue to be
- * able to read any buffered data lingering in the OS pipe buffer.
- */
- private static class ProcessPipeInputStream extends BufferedInputStream {
- private final Object closeLock = new Object();
-
- ProcessPipeInputStream(int fd) {
- super(new FileInputStream(newFileDescriptor(fd)));
- }
- private static byte[] drainInputStream(InputStream in)
- throws IOException {
- int n = 0;
- int j;
- byte[] a = null;
- while ((j = in.available()) > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- n += in.read(a, n, j);
- }
- return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- synchronized (closeLock) {
- try {
- InputStream in = this.in;
- // this stream is closed if and only if: in == null
- if (in != null) {
- byte[] stragglers = drainInputStream(in);
- in.close();
- this.in = (stragglers == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(stragglers);
- }
- } catch (IOException ignored) {}
- }
- }
-
- @Override
- public void close() throws IOException {
- // BufferedInputStream#close() is not synchronized unlike most other
- // methods. Synchronizing helps avoid race with processExited().
- synchronized (closeLock) {
- super.close();
- }
- }
- }
-
- /**
- * A buffered output stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- */
- private static class ProcessPipeOutputStream extends BufferedOutputStream {
- ProcessPipeOutputStream(int fd) {
- super(new FileOutputStream(newFileDescriptor(fd)));
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- OutputStream out = this.out;
- if (out != null) {
- try {
- out.close();
- } catch (IOException ignored) {
- // We know of no reason to get an IOException, but if
- // we do, there's nothing else to do but carry on.
- }
- this.out = ProcessBuilder.NullOutputStream.INSTANCE;
- }
- }
- }
-
- // A FileInputStream that supports the deferment of the actual close
- // operation until the last pending I/O operation on the stream has
- // finished. This is required on Solaris because we must close the stdin
- // and stdout streams in the destroy method in order to reclaim the
- // underlying file descriptors. Doing so, however, causes any thread
- // currently blocked in a read on one of those streams to receive an
- // IOException("Bad file number"), which is incompatible with historical
- // behavior. By deferring the close we allow any pending reads to see -1
- // (EOF) as they did before.
- //
- private static class DeferredCloseInputStream extends FileInputStream
- {
- DeferredCloseInputStream(FileDescriptor fd) {
- super(fd);
- }
-
- private Object lock = new Object(); // For the following fields
- private boolean closePending = false;
- private int useCount = 0;
- private InputStream streamToClose;
-
- private void raise() {
- synchronized (lock) {
- useCount++;
- }
- }
-
- private void lower() throws IOException {
- synchronized (lock) {
- useCount--;
- if (useCount == 0 && closePending) {
- streamToClose.close();
- }
- }
- }
-
- // stc is the actual stream to be closed; it might be this object, or
- // it might be an upstream object for which this object is downstream.
- //
- private void closeDeferred(InputStream stc) throws IOException {
- synchronized (lock) {
- if (useCount == 0) {
- stc.close();
- } else {
- closePending = true;
- streamToClose = stc;
- }
- }
- }
-
- public void close() throws IOException {
- synchronized (lock) {
- useCount = 0;
- closePending = false;
- }
- super.close();
- }
-
- public int read() throws IOException {
- raise();
- try {
- return super.read();
- } finally {
- lower();
- }
- }
-
- public int read(byte[] b) throws IOException {
- raise();
- try {
- return super.read(b);
- } finally {
- lower();
- }
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- raise();
- try {
- return super.read(b, off, len);
- } finally {
- lower();
- }
- }
-
- public long skip(long n) throws IOException {
- raise();
- try {
- return super.skip(n);
- } finally {
- lower();
- }
- }
-
- public int available() throws IOException {
- raise();
- try {
- return super.available();
- } finally {
- lower();
- }
- }
- }
-
- /**
- * A buffered input stream for a subprocess pipe file descriptor
- * that allows the underlying file descriptor to be reclaimed when
- * the process exits, via the processExited hook.
- *
- * This is tricky because we do not want the user-level InputStream to be
- * closed until the user invokes close(), and we need to continue to be
- * able to read any buffered data lingering in the OS pipe buffer.
- *
- * On AIX this is especially tricky, because the 'close()' system call
- * will block if another thread is at the same time blocked in a file
- * operation (e.g. 'read()') on the same file descriptor. We therefore
- * combine 'ProcessPipeInputStream' approach used on Linux and Bsd
- * with the DeferredCloseInputStream approach used on Solaris. This means
- * that every potentially blocking operation on the file descriptor
- * increments a counter before it is executed and decrements it once it
- * finishes. The 'close()' operation will only be executed if there are
- * no pending operations. Otherwise it is deferred after the last pending
- * operation has finished.
- *
- */
- private static class DeferredCloseProcessPipeInputStream
- extends BufferedInputStream {
-
- private final Object closeLock = new Object();
- private int useCount = 0;
- private boolean closePending = false;
-
- DeferredCloseProcessPipeInputStream(int fd) {
- super(new FileInputStream(newFileDescriptor(fd)));
- }
-
- private InputStream drainInputStream(InputStream in)
- throws IOException {
- int n = 0;
- int j;
- byte[] a = null;
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- j = in.available();
- }
- while (j > 0) {
- a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
- synchronized (closeLock) {
- if (buf == null) // asynchronous close()?
- return null; // discard
- n += in.read(a, n, j);
- j = in.available();
- }
- }
- return (a == null) ?
- ProcessBuilder.NullInputStream.INSTANCE :
- new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
- }
-
- /** Called by the process reaper thread when the process exits. */
- synchronized void processExited() {
- try {
- InputStream in = this.in;
- if (in != null) {
- InputStream stragglers = drainInputStream(in);
- in.close();
- this.in = stragglers;
- }
- } catch (IOException ignored) { }
- }
-
- private void raise() {
- synchronized (closeLock) {
- useCount++;
- }
- }
-
- private void lower() throws IOException {
- synchronized (closeLock) {
- useCount--;
- if (useCount == 0 && closePending) {
- closePending = false;
- super.close();
- }
- }
- }
-
- @Override
- public int read() throws IOException {
- raise();
- try {
- return super.read();
- } finally {
- lower();
- }
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- raise();
- try {
- return super.read(b);
- } finally {
- lower();
- }
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- raise();
- try {
- return super.read(b, off, len);
- } finally {
- lower();
- }
- }
-
- @Override
- public long skip(long n) throws IOException {
- raise();
- try {
- return super.skip(n);
- } finally {
- lower();
- }
- }
-
- @Override
- public int available() throws IOException {
- raise();
- try {
- return super.available();
- } finally {
- lower();
- }
- }
-
- @Override
- public void close() throws IOException {
- // BufferedInputStream#close() is not synchronized unlike most other
- // methods. Synchronizing helps avoid racing with drainInputStream().
- synchronized (closeLock) {
- if (useCount == 0) {
- super.close();
- }
- else {
- closePending = true;
- }
- }
- }
- }
-}
diff --git a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
similarity index 98%
rename from jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c
rename to jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
index 18dee4ddd41..3a962aba0a4 100644
--- a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c
+++ b/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2013, 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
@@ -203,7 +203,7 @@ effectivePathv(JNIEnv *env)
}
JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
+Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
{
parentPathv = effectivePathv(env);
CHECK_NULL(parentPathv);
@@ -230,7 +230,7 @@ Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
/* Block until a child process exits and return its exit code.
Note, can only be called once for any given pid. */
JNIEXPORT jint JNICALL
-Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
+Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env,
jobject junk,
jint pid)
{
@@ -562,7 +562,7 @@ startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
}
JNIEXPORT jint JNICALL
-Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
+Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
jobject process,
jint mode,
jbyteArray helperpath,
@@ -714,7 +714,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
}
JNIEXPORT void JNICALL
-Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env,
+Java_java_lang_ProcessImpl_destroyProcess(JNIEnv *env,
jobject junk,
jint pid,
jboolean force)
diff --git a/jdk/src/java.base/unix/native/libjava/childproc.h b/jdk/src/java.base/unix/native/libjava/childproc.h
index 75352a77b99..4dd129c2d66 100644
--- a/jdk/src/java.base/unix/native/libjava/childproc.h
+++ b/jdk/src/java.base/unix/native/libjava/childproc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -79,7 +79,7 @@ extern char **environ;
} while((_result == -1) && (errno == EINTR)); \
} while(0)
-/* These numbers must be the same as the Enum in UNIXProcess.java
+/* These numbers must be the same as the Enum in ProcessImpl.java
* Must be a better way of doing this.
*/
#define MODE_FORK 1
diff --git a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
index 921a72572b7..40c0f7150f6 100644
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
@@ -48,6 +48,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
isa_ctorID = (*env)->GetMethodID(env, cls, "",
"(Ljava/net/InetAddress;I)V");
+ initInetAddressIDs(env);
+
// implement read timeout with select.
isRcvTimeoutSupported = 0;
}
@@ -294,6 +296,8 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
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);
diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
index c4686e0fe78..b4f9f140789 100644
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
@@ -699,6 +699,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
}
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) {
diff --git a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
index 30d6d641645..8cd94eadaa9 100644
--- a/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
+++ b/jdk/src/java.base/windows/native/libnio/ch/ServerSocketChannelImpl.c
@@ -105,6 +105,7 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
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);
diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
index 30f5f67ccf2..72d8423e7dd 100644
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/Config.java
@@ -913,9 +913,9 @@ public class Config {
private static String unquote(String s) {
s = s.trim();
- if (s.isEmpty()) return s;
- if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
- s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
+ if (s.length() >= 2 &&
+ ((s.charAt(0) == '"' && s.charAt(s.length()-1) == '"') ||
+ (s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\''))) {
s = s.substring(1, s.length()-1).trim();
}
return s;
diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java
index 4c63fe1302c..7bf3ac60c58 100644
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbKdcRep.java
@@ -62,7 +62,8 @@ abstract class KrbKdcRep {
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
}
- for (int i = 1; i < 6; i++) {
+ // We allow KDC to return a non-forwardable ticket if request has -f
+ for (int i = 2; i < 6; i++) {
if (req.reqBody.kdcOptions.get(i) !=
rep.encKDCRepPart.flags.get(i)) {
if (Krb5.DEBUG) {
diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java
index 45f25e825ce..a8b3404da36 100644
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbTgsReq.java
@@ -149,19 +149,11 @@ public class KrbTgsReq {
ctime = KerberosTime.now();
// check if they are valid arguments. The optional fields
- // should be consistent with settings in KDCOptions.
-
- // TODO: Is this necessary? If the TGT is not FORWARDABLE,
- // you can still request for a FORWARDABLE ticket, just the
- // KDC will give you a non-FORWARDABLE one. Even if you
- // cannot use the ticket expected, it still contains info.
- // This means there will be problem later. We already have
- // flags check in KrbTgsRep. Of course, sometimes the KDC
- // will not issue the ticket at all.
+ // should be consistent with settings in KDCOptions.
if (options.get(KDCOptions.FORWARDABLE) &&
(!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {
- throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
+ options.set(KDCOptions.FORWARDABLE, false);
}
if (options.get(KDCOptions.FORWARDED)) {
if (!(asCreds.flags.get(KDCOptions.FORWARDABLE)))
diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java
index b6a36777599..14620e94483 100644
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/CredentialsUtil.java
@@ -58,6 +58,9 @@ public class CredentialsUtil {
// TODO: we do not support kerberos referral now
throw new KrbException("Cross realm impersonation not supported");
}
+ if (!ccreds.isForwardable()) {
+ throw new KrbException("S4U2self needs a FORWARDABLE ticket");
+ }
KrbTgsReq req = new KrbTgsReq(
ccreds,
ccreds.getClient(),
@@ -68,6 +71,9 @@ public class CredentialsUtil {
if (!creds.getClient().equals(client)) {
throw new KrbException("S4U2self request not honored by KDC");
}
+ if (!creds.isForwardable()) {
+ throw new KrbException("S4U2self ticket must be FORWARDABLE");
+ }
return creds;
}
diff --git a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c
index db97c948ee6..6a5e2cbbb8c 100644
--- a/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c
+++ b/jdk/src/jdk.sctp/unix/native/libsctp/SctpNet.c
@@ -316,11 +316,12 @@ void initializeISA
if (isaCls == 0) {
jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
CHECK_NULL(c);
+ isaCtrID = (*env)->GetMethodID(env, c, "",
+ "(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, "",
- "(Ljava/net/InetAddress;I)V");
}
}
diff --git a/jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c b/jdk/src/jdk.security.auth/solaris/native/libjaas/Solaris.c
similarity index 100%
rename from jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c
rename to jdk/src/jdk.security.auth/solaris/native/libjaas/Solaris.c
diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt
index c6c35f2e4d6..fde49fa1203 100644
--- a/jdk/test/ProblemList.txt
+++ b/jdk/test/ProblemList.txt
@@ -128,9 +128,6 @@ java/lang/ClassLoader/deadlock/GetResource.java generic-all
# jdk_instrument
-# 8058536
-java/lang/instrument/NativeMethodPrefixAgent.java generic-all
-
# 8061177
java/lang/instrument/RedefineBigClass.sh generic-all
java/lang/instrument/RetransformBigClass.sh generic-all
@@ -246,6 +243,9 @@ sun/security/tools/keytool/standard.sh solaris-all
# 8062758
java/security/Security/ClassLoaderDeadlock/Deadlock2.sh generic-all
+# 8026393
+sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all
+
############################################################################
# jdk_sound
diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups
index 4d4705c2ba4..7acb6ab9147 100644
--- a/jdk/test/TEST.groups
+++ b/jdk/test/TEST.groups
@@ -628,7 +628,6 @@ needs_compact2 = \
sun/net/www/protocol/http \
java/io/BufferedReader/Lines.java \
java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java \
- java/lang/CharSequence/DefaultTest.java \
java/lang/IntegralPrimitiveToString.java \
java/lang/PrimitiveSumMinMaxTest.java \
java/lang/String/StringJoinTest.java \
diff --git a/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java b/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java
index 323a05e8410..ae16712c97f 100644
--- a/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java
+++ b/jdk/test/java/io/Serializable/subclassGC/SubclassGC.java
@@ -50,8 +50,9 @@ public class SubclassGC {
}
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);
diff --git a/jdk/test/java/io/Serializable/subclassGC/security.policy b/jdk/test/java/io/Serializable/subclassGC/security.policy
index 894df4cd2dd..a3ef804b37a 100644
--- a/jdk/test/java/io/Serializable/subclassGC/security.policy
+++ b/jdk/test/java/io/Serializable/subclassGC/security.policy
@@ -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 "<>", "read";
};
diff --git a/jdk/test/java/lang/CharSequence/DefaultTest.java b/jdk/test/java/lang/CharSequence/DefaultTest.java
deleted file mode 100644
index 0595f745174..00000000000
--- a/jdk/test/java/lang/CharSequence/DefaultTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.PrimitiveIterator;
-import java.util.Spliterator;
-import java.util.stream.Collectors;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.*;
-
-/*
- * @test
- * @summary Unit test for CharSequence default methods
- * @bug 8012665 8025002
- * @run testng DefaultTest
- */
-
-@Test(groups = "lib")
-public class DefaultTest {
-
- @Test(expectedExceptions = NoSuchElementException.class)
- public void testEmptyChars() {
- PrimitiveIterator.OfInt s = "".chars().iterator();
- assertFalse(s.hasNext());
- int ch = s.nextInt();
- }
-
- public void testSimpleChars() {
- List list = "abc".chars().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int) 'a', (int) 'b', (int) 'c'));
- }
-
- public void testCodePointsCharacteristics() {
- Spliterator.OfInt s = "".codePoints().spliterator();
- assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
- assertTrue(s.hasCharacteristics(Spliterator.ORDERED));
- }
-
- @Test(expectedExceptions = NoSuchElementException.class)
- public void testEmptyCodePoints() {
- PrimitiveIterator.OfInt s = "".codePoints().iterator();
- assertFalse(s.hasNext());
- int cp = s.nextInt();
- }
-
- public void testSimpleCodePoints() {
- List list = "abc".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'a', (int)'b', (int)'c'));
- }
-
- public void testUndefCodePoints() {
- List list = "X\ufffeY".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'X', 0xFFFE, (int)'Y'));
- }
-
- public void testSurrogatePairing() {
- // U+1D11E = MUSICAL SYMBOL G CLEF
- // equivalent to surrogate pair U+D834 U+DD1E
- List list;
- final int GCLEF = 0x1d11e;
-
- list = "\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(GCLEF));
- list = "A\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'A', GCLEF));
- list = "\ud834\udd1eB".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(GCLEF, (int)'B'));
- list = "X\ud834\udd1eY".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList((int)'X', GCLEF, (int)'Y'));
- }
-
- public void testUndefUnpaired() {
- List list = "W\udd1eX\ud834Y\ufffeZ".codePoints().boxed().collect(Collectors.toList());
- assertEquals(list, Arrays.asList(
- (int)'W', 0xdd1e, (int)'X', 0xd834, (int)'Y', 0xfffe, (int)'Z'));
- }
-}
diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java
index b81853bd9ee..03d165f7111 100644
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java
@@ -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
@@ -26,7 +26,7 @@
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
- * 4947220 7018606 7034570 4244896 5049299 8003488
+ * 4947220 7018606 7034570 4244896 5049299 8003488 8054494
* @summary Basic tests for Process and Environment Variable code
* @run main/othervm/timeout=300 Basic
* @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
@@ -2042,7 +2042,7 @@ public class Basic {
final Object deferred;
Class> c = s.getClass();
if (c.getName().equals(
- "java.lang.UNIXProcess$DeferredCloseInputStream"))
+ "java.lang.ProcessImpl$DeferredCloseInputStream"))
{
deferred = s;
} else {
@@ -2059,13 +2059,11 @@ public class Basic {
Thread.yield();
}
} else if (s instanceof BufferedInputStream) {
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- Unsafe unsafe = (Unsafe)f.get(null);
-
- while (unsafe.tryMonitorEnter(s)) {
- unsafe.monitorExit(s);
- Thread.sleep(1);
+ // Wait until after the s.read occurs in "thread" by
+ // checking when the input stream monitor is acquired
+ // (BufferedInputStream.read is synchronized)
+ while (!isLocked(s, 10)) {
+ Thread.sleep(100);
}
}
p.destroy();
@@ -2565,4 +2563,21 @@ public class Basic {
catch (Throwable t) {
if (k.isAssignableFrom(t.getClass())) pass();
else unexpected(t);}}
+
+ static boolean isLocked(final Object monitor, final long millis) throws InterruptedException {
+ return new Thread() {
+ volatile boolean unlocked;
+
+ @Override
+ public void run() {
+ synchronized (monitor) { unlocked = true; }
+ }
+
+ boolean isLocked() throws InterruptedException {
+ start();
+ join(millis);
+ return !unlocked;
+ }
+ }.isLocked();
+ }
}
diff --git a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java
index 39848fa4aab..cd09b070aa8 100644
--- a/jdk/test/java/lang/ref/OOMEInReferenceHandler.java
+++ b/jdk/test/java/lang/ref/OOMEInReferenceHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,7 +25,7 @@
* @test
* @bug 7038914 8016341
* @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
- * @run main/othervm -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
+ * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
* @author peter.levart@gmail.com
*/
diff --git a/jdk/test/java/net/ServerSocket/AcceptInheritHandle.java b/jdk/test/java/net/ServerSocket/AcceptInheritHandle.java
new file mode 100644
index 00000000000..ce175f2f490
--- /dev/null
+++ b/jdk/test/java/net/ServerSocket/AcceptInheritHandle.java
@@ -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 supplier;
+ ServerSocketProducer(Supplier supplier) {
+ this.supplier = supplier;
+ }
+ Supplier 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 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);
+ }
+ }
+}
diff --git a/jdk/test/java/net/Socket/GetLocalAddress.java b/jdk/test/java/net/Socket/GetLocalAddress.java
index e9573d2eff1..3e98bc9f294 100644
--- a/jdk/test/java/net/Socket/GetLocalAddress.java
+++ b/jdk/test/java/net/Socket/GetLocalAddress.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 4106601 8026245
+ * @bug 4106601 8026245 8071424
* @run main/othervm GetLocalAddress
* @run main/othervm -Djava.net.preferIPv4Stack=true GetLocalAddress
* @run main/othervm -Djava.net.preferIPv6Addresses=true GetLocalAddress
@@ -39,6 +39,8 @@ public class GetLocalAddress implements Runnable {
static int port;
public static void main(String args[]) throws Exception {
+ testBindNull();
+
boolean error = true;
int linger = 65546;
int value = 0;
@@ -66,4 +68,18 @@ public class GetLocalAddress implements Runnable {
}
}
+ static void testBindNull() throws Exception {
+ try (Socket soc = new Socket()) {
+ soc.bind(null);
+ if (!soc.isBound())
+ throw new RuntimeException(
+ "should be bound after bind(null)");
+ if (soc.getLocalPort() <= 0)
+ throw new RuntimeException(
+ "bind(null) failed, local port: " + soc.getLocalPort());
+ if (soc.getLocalAddress() == null)
+ throw new RuntimeException(
+ "bind(null) failed, local address is null");
+ }
+ }
}
diff --git a/jdk/test/java/util/ResourceBundle/Bug6287579.java b/jdk/test/java/util/ResourceBundle/Bug6287579.java
deleted file mode 100644
index 43e7e8c2b19..00000000000
--- a/jdk/test/java/util/ResourceBundle/Bug6287579.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/*
- * @test
- * @bug 6287579
- * @summary Make sure that getContents() of ListResourceBundle subclasses is 'protected'
- * and returns a different Object[]][] instance in each invocation.
- */
-
-import java.lang.reflect.*;
-import java.util.*;
-
-public class Bug6287579 {
- static final Locale ROOT = new Locale("");
-
- static final String[] baseNames = {
- "sun.text.resources.BreakIteratorInfo",
- "sun.text.resources.FormatData",
- "sun.text.resources.CollationData",
- "sun.util.resources.LocaleNames",
- "sun.util.resources.TimeZoneNames",
-
- // Make sure the properties-to-class conversion tool generates
- // the proper getContents().
- "sun.awt.resources.awt",
- };
-
- public static void main(String[] args) throws Exception {
- int errors = 0;
-
- List locales = new ArrayList();
- locales.addAll(Arrays.asList(Locale.getAvailableLocales()));
- locales.add(ROOT);
-
- for (Locale locale : locales) {
- for (String base : baseNames) {
- String className = getResourceName(base, locale);
- errors += checkGetContents(className);
- }
- }
- if (errors > 0) {
- throw new RuntimeException(errors + " errors found");
- }
- }
-
- static int checkGetContents(String className) throws Exception {
- int err = 0;
- try {
- Class clazz = Class.forName(className);
- Method getContentsMethod = clazz.getDeclaredMethod("getContents",
- (Class[]) null);
- if (!Modifier.isProtected(getContentsMethod.getModifiers())) {
- System.err.println(className + ": not protected");
- err++;
- }
- getContentsMethod.setAccessible(true);
- Object bundle = clazz.newInstance();
- Object o1 = getContentsMethod.invoke(bundle, (Object[]) null);
- Object o2 = getContentsMethod.invoke(bundle, (Object[]) null);
- if (o1 == o2) {
- System.err.println(className + ": same instance returned");
- err++;
- }
- } catch (ClassNotFoundException ce) {
- // Skip nonexistent classes
- } catch (NoSuchMethodException me) {
- System.out.println(className + ": no declared getContents()");
- }
- return err;
- }
-
- static String getResourceName(String base, Locale locale) {
- if (locale.equals(ROOT)) {
- return base;
- }
- StringBuilder sb = new StringBuilder(base);
- sb.append('_').append(locale.getLanguage());
- if (locale.getCountry().length() > 0
- || locale.getVariant().length() > 0) {
- sb.append('_').append(locale.getCountry());
- }
- if (locale.getVariant().length() > 0) {
- sb.append('_').append(locale.getVariant());
- }
- return sb.toString();
- }
-}
diff --git a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java
index f226a82b439..9815340e2a5 100644
--- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
/**
* @test
- * @bug 8020156 8020009 8022326 8012913 8024405 8024408
+ * @bug 8020156 8020009 8022326 8012913 8024405 8024408 8071477
* @run testng SpliteratorCharacteristics
*/
@@ -59,6 +59,57 @@ import static org.testng.Assert.*;
@Test
public class SpliteratorCharacteristics {
+ public void testSpliteratorFromCharSequence() {
+ class CharSequenceImpl implements CharSequence {
+ final String s;
+
+ public CharSequenceImpl(String s) {
+ this.s = s;
+ }
+
+ @Override
+ public int length() {
+ return s.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return s.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return s.subSequence(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return s;
+ }
+ }
+
+ CharSequence cs = "A";
+ Spliterator.OfInt s = cs.chars().spliterator();
+ assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED |
+ Spliterator.SIZED | Spliterator.SUBSIZED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ s = cs.codePoints().spliterator();
+ assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+
+ for (CharSequence c : Arrays.asList(new CharSequenceImpl("A"),
+ new StringBuilder("A"),
+ new StringBuffer("A"))) {
+ s = cs.chars().spliterator();
+ assertCharacteristics(s, Spliterator.ORDERED |
+ Spliterator.SIZED | Spliterator.SUBSIZED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ s = cs.codePoints().spliterator();
+ assertCharacteristics(s, Spliterator.ORDERED);
+ assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
+ }
+ }
+
public void testSpliteratorFromCollection() {
List l = Arrays.asList(1, 2, 3, 4);
diff --git a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
index 69c7cf57436..d9593001b04 100644
--- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
+++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
* @test
* @summary Spliterator traversing and splitting tests
* @run testng SpliteratorTraversingAndSplittingTest
- * @bug 8020016
+ * @bug 8020016 8071477
*/
import org.testng.annotations.DataProvider;
@@ -85,7 +85,38 @@ import static org.testng.Assert.assertEquals;
@Test
public class SpliteratorTraversingAndSplittingTest {
- private static List SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+ private static final List SIZES = Arrays.asList(0, 1, 10, 100, 1000);
+
+ private static final String LOW = new String(new char[] {Character.MIN_LOW_SURROGATE});
+ private static final String HIGH = new String(new char[] {Character.MIN_HIGH_SURROGATE});
+ private static final String HIGH_LOW = HIGH + LOW;
+ private static final String CHAR_HIGH_LOW = "A" + HIGH_LOW;
+ private static final String HIGH_LOW_CHAR = HIGH_LOW + "A";
+ private static final String CHAR_HIGH_LOW_CHAR = "A" + HIGH_LOW + "A";
+
+ private static final List STRINGS = generateTestStrings();
+
+ private static List generateTestStrings() {
+ List strings = new ArrayList<>();
+ for (int n : Arrays.asList(1, 2, 3, 16, 17)) {
+ strings.add(generate("A", n));
+ strings.add(generate(LOW, n));
+ strings.add(generate(HIGH, n));
+ strings.add(generate(HIGH_LOW, n));
+ strings.add(generate(CHAR_HIGH_LOW, n));
+ strings.add(generate(HIGH_LOW_CHAR, n));
+ strings.add(generate(CHAR_HIGH_LOW_CHAR, n));
+ }
+ return strings;
+ }
+
+ private static String generate(String s, int n) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < n; i++) {
+ sb.append(s);
+ }
+ return sb.toString();
+ }
private static class SpliteratorDataBuilder {
List