OpenJDK / amber / amber
changeset 28829:a8c81ce8d333
Merge
author | ctornqvi |
---|---|
date | Wed, 04 Feb 2015 18:22:46 -0800 |
parents | 6a45344e2b3f a9eac944c97d |
children | 627c26f2e54b |
files | hotspot/make/linux/makefiles/build_vm_def.sh jdk/make/data/checkdeps/refs.allowed jdk/make/src/classes/build/tools/deps/CheckDeps.java jdk/src/java.base/aix/native/libnet/java/net/aix_close.c jdk/src/java.base/unix/classes/java/lang/UNIXProcess.java jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c jdk/src/java.base/unix/native/libjava/java_props_macosx.c jdk/src/java.base/unix/native/libjava/java_props_macosx.h jdk/src/java.base/unix/native/libnet/bsd_close.c jdk/src/java.base/unix/native/libnet/linux_close.c jdk/src/java.base/unix/native/libnet/solaris_close.c jdk/src/jdk.security.auth/unix/native/libjaas/Solaris.c jdk/test/java/lang/CharSequence/DefaultTest.java jdk/test/java/util/ResourceBundle/Bug6287579.java |
diffstat | 233 files changed, 13595 insertions(+), 5980 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -290,3 +290,4 @@ bfc24ae2b900187585079bb11e66e459d1e525fe jdk9-b45 722378bc599e38d9a1dd484de30f10dfd7b21438 jdk9-b46 8327024a99559982b848e9c2191da9c0bf8838fd jdk9-b47 +b2f9702efbe95527ea3a991474fda23987ff1c5c jdk9-b48
--- a/.hgtags-top-repo Tue Feb 03 12:49:33 2015 +0100 +++ b/.hgtags-top-repo Wed Feb 04 18:22:46 2015 -0800 @@ -290,3 +290,4 @@ 3dd628fde2086218d548841022ee8436b6b88185 jdk9-b45 12f1e276447bcc81516e85367d53e4f08897049d jdk9-b46 b6cca3e6175a69f39e5799b7349ddb0176630291 jdk9-b47 +0064e246d83f6f9fc245c19b6d05041ecaf4b6d4 jdk9-b48
--- a/common/autoconf/basics.m4 Tue Feb 03 12:49:33 2015 +0100 +++ b/common/autoconf/basics.m4 Wed Feb 04 18:22:46 2015 -0800 @@ -987,3 +987,26 @@ IS_RECONFIGURE=no fi ]) + +# Check for support for specific options in bash +AC_DEFUN_ONCE([BASIC_CHECK_BASH_OPTIONS], +[ + # Test if bash supports pipefail. + AC_MSG_CHECKING([if bash supports pipefail]) + if ${BASH} -c 'set -o pipefail'; then + BASH_ARGS="$BASH_ARGS -o pipefail" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + AC_MSG_CHECKING([if bash supports errexit (-e)]) + if ${BASH} -e -c 'true'; then + BASH_ARGS="$BASH_ARGS -e" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + fi + + AC_SUBST(BASH_ARGS) +])
--- a/common/autoconf/bootcycle-spec.gmk.in Tue Feb 03 12:49:33 2015 +0100 +++ b/common/autoconf/bootcycle-spec.gmk.in Wed Feb 04 18:22:46 2015 -0800 @@ -46,8 +46,12 @@ BOOT_JDK := $(JDK_IMAGE_DIR) # The bootcycle build has a different output directory -BUILD_OUTPUT:=@BUILD_OUTPUT@/bootcycle-build -SJAVAC_SERVER_DIR:=$(subst @BUILD_OUTPUT@,$(BUILD_OUTPUT),$(SJAVAC_SERVER_DIR)) +OLD_BUILD_OUTPUT:=@BUILD_OUTPUT@ +BUILD_OUTPUT:=$(OLD_BUILD_OUTPUT)/bootcycle-build +# The HOTSPOT_DIST dir is not defined relative to BUILD_OUTPUT in spec.gmk. Must not +# use space in this patsubst to avoid leading space in HOTSPOT_DIST. +HOTSPOT_DIST:=$(patsubst $(OLD_BUILD_OUTPUT)%,$(BUILD_OUTPUT)%,$(HOTSPOT_DIST)) +SJAVAC_SERVER_DIR:=$(patsubst $(OLD_BUILD_OUTPUT)%, $(BUILD_OUTPUT)%, $(SJAVAC_SERVER_DIR)) JAVA_CMD:=$(BOOT_JDK)/bin/java JAVAC_CMD:=$(BOOT_JDK)/bin/javac
--- a/common/autoconf/configure.ac Tue Feb 03 12:49:33 2015 +0100 +++ b/common/autoconf/configure.ac Wed Feb 04 18:22:46 2015 -0800 @@ -113,6 +113,7 @@ # Setup tools that requires more complex handling, or that is not needed by the configure script. BASIC_SETUP_COMPLEX_TOOLS +BASIC_CHECK_BASH_OPTIONS # Check if pkg-config is available. PKG_PROG_PKG_CONFIG
--- a/common/autoconf/generated-configure.sh Tue Feb 03 12:49:33 2015 +0100 +++ b/common/autoconf/generated-configure.sh Wed Feb 04 18:22:46 2015 -0800 @@ -853,6 +853,7 @@ OS_VERSION_MINOR OS_VERSION_MAJOR PKG_CONFIG +BASH_ARGS CODESIGN XATTR DSYMUTIL @@ -3522,6 +3523,9 @@ +# Check for support for specific options in bash + + # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -4329,7 +4333,7 @@ #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1420811523 +DATE_WHEN_GENERATED=1421247827 ############################################################################### # @@ -19609,6 +19613,32 @@ fi + # Test if bash supports pipefail. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports pipefail" >&5 +$as_echo_n "checking if bash supports pipefail... " >&6; } + if ${BASH} -c 'set -o pipefail'; then + BASH_ARGS="$BASH_ARGS -o pipefail" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if bash supports errexit (-e)" >&5 +$as_echo_n "checking if bash supports errexit (-e)... " >&6; } + if ${BASH} -e -c 'true'; then + BASH_ARGS="$BASH_ARGS -e" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + + + + # Check if pkg-config is available. @@ -27408,8 +27438,8 @@ # The trailing space for everyone except PATH is no typo, but is needed due # to trailing \ in the Windows paths. These will be stripped later. $ECHO "$WINPATH_BASH -c 'echo VS_PATH="'\"$PATH\" > set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE - $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE\;$include \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE - $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB\;$lib \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE + $ECHO "$WINPATH_BASH -c 'echo VS_INCLUDE="'\"$INCLUDE \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE + $ECHO "$WINPATH_BASH -c 'echo VS_LIB="'\"$LIB \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE $ECHO "$WINPATH_BASH -c 'echo VCINSTALLDIR="'\"$VCINSTALLDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE $ECHO "$WINPATH_BASH -c 'echo WindowsSdkDir="'\"$WindowsSdkDir \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE $ECHO "$WINPATH_BASH -c 'echo WINDOWSSDKDIR="'\"$WINDOWSSDKDIR \" >> set-vs-env.sh' >> $EXTRACT_VC_ENV_BAT_FILE
--- a/common/autoconf/spec.gmk.in Tue Feb 03 12:49:33 2015 +0100 +++ b/common/autoconf/spec.gmk.in Wed Feb 04 18:22:46 2015 -0800 @@ -78,6 +78,11 @@ OUTPUT_SYNC_SUPPORTED:=@OUTPUT_SYNC_SUPPORTED@ OUTPUT_SYNC:=@OUTPUT_SYNC@ +# Override the shell with bash +BASH:=@BASH@ +BASH_ARGS:=@BASH_ARGS@ +SHELL:=$(BASH) $(BASH_ARGS) + # The "human readable" name of this configuration CONF_NAME:=@CONF_NAME@ @@ -243,7 +248,7 @@ HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images -TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/testmake +TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support HOTSPOT_DIST=@HOTSPOT_DIST@ @@ -495,7 +500,6 @@ # Tools adhering to a minimal and common standard of posix compliance. AWK:=@AWK@ BASENAME:=@BASENAME@ -BASH:=@BASH@ CAT:=@CAT@ CCACHE:=@CCACHE@ # CD is going away, but remains to cater for legacy makefiles.
--- a/corba/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/corba/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -290,3 +290,4 @@ 9e3f2bed80c0e5a84a256ce41f1d10c5ade48466 jdk9-b45 326f2068b4a4c05e2fa27d6acf93eba7b54b090d jdk9-b46 ee8447ca632e1d39180b4767c749db101bff7314 jdk9-b47 +a13c49c5f2899b702652a460ed7aa73123e671e6 jdk9-b48
--- a/hotspot/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -450,3 +450,4 @@ 5dc8184af1e2bb30b0103113d1f1a58a21a80c37 jdk9-b45 a184ee1d717297bd35b7c3e35393e137921a3ed2 jdk9-b46 3b241fb72b8925b75941d612db762a6d5da66d02 jdk9-b47 +cc775a4a24c7f5d9e624b4205e9fbd48a17331f6 jdk9-b48
--- a/hotspot/make/aix/makefiles/xlc.make Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/make/aix/makefiles/xlc.make Wed Feb 04 18:22:46 2015 -0800 @@ -74,6 +74,12 @@ # no xlc counterpart for -fcheck-new # CFLAGS += -fcheck-new +# We need to define this on the command line if we want to use the the +# predefined format specifiers from "inttypes.h". Otherwise system headrs +# can indirectly include inttypes.h before we define __STDC_FORMAT_MACROS +# in globalDefinitions.hpp +CFLAGS += -D__STDC_FORMAT_MACROS + ARCHFLAG = -q64 CFLAGS += $(ARCHFLAG)
--- a/hotspot/make/linux/makefiles/build_vm_def.sh Tue Feb 03 12:49:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#!/bin/sh - -# If we're cross compiling use that path for nm -if [ "$CROSS_COMPILE_ARCH" != "" ]; then -NM=$ALT_COMPILER_PATH/nm -else -NM=nm -fi - -$NM --defined-only $* \ - | awk '{ - if ($3 ~ /^_ZTV/ || $3 ~ /^gHotSpotVM/) print "\t" $3 ";" - if ($3 ~ /^UseSharedSpaces$/) print "\t" $3 ";" - if ($3 ~ /^_ZN9Arguments17SharedArchivePathE$/) print "\t" $3 ";" - }' \ - | sort -u
--- a/hotspot/make/linux/makefiles/vm.make Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/make/linux/makefiles/vm.make Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -239,8 +239,14 @@ rm -f $@ cat $^ > $@ +VMDEF_PAT = ^_ZTV +VMDEF_PAT := ^gHotSpotVM|$(VMDEF_PAT) +VMDEF_PAT := ^UseSharedSpaces$$|$(VMDEF_PAT) +VMDEF_PAT := ^_ZN9Arguments17SharedArchivePathE$$|$(VMDEF_PAT) + vm.def: $(Res_Files) $(Obj_Files) - sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@ + $(QUIETLY) $(NM) --defined-only $(Obj_Files) | sort -k3 -u | \ + awk '$$3 ~ /$(VMDEF_PAT)/ { print "\t" $$3 ";" }' > $@ mapfile_ext: rm -f $@
--- a/hotspot/src/cpu/sparc/vm/sparc.ad Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/cpu/sparc/vm/sparc.ad Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ // -// Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -2996,7 +2996,7 @@ %} enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ - Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; + Label Lchar, Lchar_loop, Ldone; MacroAssembler _masm(&cbuf); Register str1_reg = reg_to_register_object($str1$$reg);
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -6194,7 +6194,7 @@ ShortBranchVerifier sbv(this); assert(UseSSE42Intrinsics, "SSE4.2 is required"); - // This method uses pcmpestri inxtruction with bound registers + // This method uses pcmpestri instruction with bound registers // inputs: // xmm - substring // rax - substring length (elements count) @@ -6355,7 +6355,7 @@ // assert(int_cnt2 == -1 || (0 < int_cnt2 && int_cnt2 < 8), "should be != 0"); - // This method uses pcmpestri inxtruction with bound registers + // This method uses pcmpestri instruction with bound registers // inputs: // xmm - substring // rax - substring length (elements count) @@ -6644,7 +6644,6 @@ // start from first character again because it has aligned address. int stride2 = 16; int adr_stride = stride << scale; - int adr_stride2 = stride2 << scale; assert(result == rax && cnt2 == rdx && cnt1 == rcx, "pcmpestri"); // rax and rdx are used by pcmpestri as elements counters @@ -6743,7 +6742,7 @@ // inputs: // vec1- substring // rax - negative string length (elements count) - // mem - scaned string + // mem - scanned string // rdx - string length (elements count) // pcmpmask - cmp mode: 11000 (string compare with negated result) // + 00 (unsigned bytes) or + 01 (unsigned shorts)
--- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -31,6 +31,7 @@ #include "os_aix.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/perfMemory.hpp" +#include "services/memTracker.hpp" #include "utilities/exceptions.hpp" // put OS-includes here @@ -196,12 +197,37 @@ return pid; } +// Check if the given statbuf is considered a secure directory for +// the backing store files. Returns true if the directory is considered +// a secure location. Returns false if the statbuf is a symbolic link or +// if an error occurred. +static bool is_statbuf_secure(struct stat *statp) { + if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) { + // The path represents a link or some non-directory file type, + // which is not what we expected. Declare it insecure. + // + return false; + } + // We have an existing directory, check if the permissions are safe. + if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) { + // The directory is open for writing and could be subjected + // to a symlink or a hard link attack. Declare it insecure. + return false; + } + // See if the uid of the directory matches the effective uid of the process. + // + if (statp->st_uid != geteuid()) { + // The directory was not created by this user, declare it insecure. + return false; + } + return true; +} -// check if the given path is considered a secure directory for + +// Check if the given path is considered a secure directory for // the backing store files. Returns true if the directory exists // and is considered a secure location. Returns false if the path // is a symbolic link or if an error occurred. -// static bool is_directory_secure(const char* path) { struct stat statbuf; int result = 0; @@ -211,38 +237,276 @@ return false; } - // the path exists, now check it's mode - if (S_ISLNK(statbuf.st_mode) || !S_ISDIR(statbuf.st_mode)) { - // the path represents a link or some non-directory file type, - // which is not what we expected. declare it insecure. - // + // The path exists, see if it is secure. + return is_statbuf_secure(&statbuf); +} + +// (Taken over from Solaris to support the O_NOFOLLOW case on AIX.) +// Check if the given directory file descriptor is considered a secure +// directory for the backing store files. Returns true if the directory +// exists and is considered a secure location. Returns false if the path +// is a symbolic link or if an error occurred. +static bool is_dirfd_secure(int dir_fd) { + struct stat statbuf; + int result = 0; + + RESTARTABLE(::fstat(dir_fd, &statbuf), result); + if (result == OS_ERR) { + return false; + } + + // The path exists, now check its mode. + return is_statbuf_secure(&statbuf); +} + + +// Check to make sure fd1 and fd2 are referencing the same file system object. +static bool is_same_fsobject(int fd1, int fd2) { + struct stat statbuf1; + struct stat statbuf2; + int result = 0; + + RESTARTABLE(::fstat(fd1, &statbuf1), result); + if (result == OS_ERR) { + return false; + } + RESTARTABLE(::fstat(fd2, &statbuf2), result); + if (result == OS_ERR) { + return false; + } + + if ((statbuf1.st_ino == statbuf2.st_ino) && + (statbuf1.st_dev == statbuf2.st_dev)) { + return true; + } else { return false; } - else { - // we have an existing directory, check if the permissions are safe. - // - if ((statbuf.st_mode & (S_IWGRP|S_IWOTH)) != 0) { - // the directory is open for writing and could be subjected - // to a symlnk attack. declare it insecure. - // - return false; +} + +// Helper functions for open without O_NOFOLLOW which is not present on AIX 5.3/6.1. +// We use the jdk6 implementation here. +#ifndef O_NOFOLLOW +// The O_NOFOLLOW oflag doesn't exist before solaris 5.10, this is to simulate that behaviour +// was done in jdk 5/6 hotspot by Oracle this way +static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool use_mode) { + struct stat orig_st; + struct stat new_st; + bool create; + int error; + int fd; + + create = false; + + if (lstat(path, &orig_st) != 0) { + if (errno == ENOENT && (oflag & O_CREAT) != 0) { + // File doesn't exist, but_we want to create it, add O_EXCL flag + // to make sure no-one creates it (or a symlink) before us + // This works as we expect with symlinks, from posix man page: + // 'If O_EXCL and O_CREAT are set, and path names a symbolic + // link, open() shall fail and set errno to [EEXIST]'. + oflag |= O_EXCL; + create = true; + } else { + // File doesn't exist, and we are not creating it. + return OS_ERR; + } + } else { + // Lstat success, check if existing file is a link. + if ((orig_st.st_mode & S_IFMT) == S_IFLNK) { + // File is a symlink. + errno = ELOOP; + return OS_ERR; + } + } + + if (use_mode == true) { + fd = open(path, oflag, mode); + } else { + fd = open(path, oflag); + } + + if (fd == OS_ERR) { + return fd; + } + + // Can't do inode checks on before/after if we created the file. + if (create == false) { + if (fstat(fd, &new_st) != 0) { + // Keep errno from fstat, in case close also fails. + error = errno; + ::close(fd); + errno = error; + return OS_ERR; + } + + if (orig_st.st_dev != new_st.st_dev || orig_st.st_ino != new_st.st_ino) { + // File was tampered with during race window. + ::close(fd); + errno = EEXIST; + if (PrintMiscellaneous && Verbose) { + warning("possible file tampering attempt detected when opening %s", path); + } + return OS_ERR; } } + + return fd; +} + +static int open_o_nofollow(const char* path, int oflag, mode_t mode) { + return open_o_nofollow_impl(path, oflag, mode, true); +} + +static int open_o_nofollow(const char* path, int oflag) { + return open_o_nofollow_impl(path, oflag, 0, false); +} +#endif + +// Open the directory of the given path and validate it. +// Return a DIR * of the open directory. +static DIR *open_directory_secure(const char* dirname) { + // Open the directory using open() so that it can be verified + // to be secure by calling is_dirfd_secure(), opendir() and then check + // to see if they are the same file system object. This method does not + // introduce a window of opportunity for the directory to be attacked that + // calling opendir() and is_directory_secure() does. + int result; + DIR *dirp = NULL; + + // No O_NOFOLLOW defined at buildtime, and it is not documented for open; + // so provide a workaround in this case. +#ifdef O_NOFOLLOW + RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); +#else + // workaround (jdk6 coding) + RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result); +#endif + + if (result == OS_ERR) { + // Directory doesn't exist or is a symlink, so there is nothing to cleanup. + if (PrintMiscellaneous && Verbose) { + if (errno == ELOOP) { + warning("directory %s is a symlink and is not secure\n", dirname); + } else { + warning("could not open directory %s: %s\n", dirname, strerror(errno)); + } + } + return dirp; + } + int fd = result; + + // Determine if the open directory is secure. + if (!is_dirfd_secure(fd)) { + // The directory is not a secure directory. + os::close(fd); + return dirp; + } + + // Open the directory. + dirp = ::opendir(dirname); + if (dirp == NULL) { + // The directory doesn't exist, close fd and return. + os::close(fd); + return dirp; + } + + // Check to make sure fd and dirp are referencing the same file system object. + if (!is_same_fsobject(fd, dirp->dd_fd)) { + // The directory is not secure. + os::close(fd); + os::closedir(dirp); + dirp = NULL; + return dirp; + } + + // Close initial open now that we know directory is secure + os::close(fd); + + return dirp; +} + +// NOTE: The code below uses fchdir(), open() and unlink() because +// fdopendir(), openat() and unlinkat() are not supported on all +// versions. Once the support for fdopendir(), openat() and unlinkat() +// is available on all supported versions the code can be changed +// to use these functions. + +// Open the directory of the given path, validate it and set the +// current working directory to it. +// Return a DIR * of the open directory and the saved cwd fd. +// +static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { + + // Open the directory. + DIR* dirp = open_directory_secure(dirname); + if (dirp == NULL) { + // Directory doesn't exist or is insecure, so there is nothing to cleanup. + return dirp; + } + int fd = dirp->dd_fd; + + // Open a fd to the cwd and save it off. + int result; + RESTARTABLE(::open(".", O_RDONLY), result); + if (result == OS_ERR) { + *saved_cwd_fd = -1; + } else { + *saved_cwd_fd = result; + } + + // Set the current directory to dirname by using the fd of the directory. + result = fchdir(fd); + + return dirp; +} + +// Close the directory and restore the current working directory. +static void close_directory_secure_cwd(DIR* dirp, int saved_cwd_fd) { + + int result; + // If we have a saved cwd change back to it and close the fd. + if (saved_cwd_fd != -1) { + result = fchdir(saved_cwd_fd); + ::close(saved_cwd_fd); + } + + // Close the directory. + os::closedir(dirp); +} + +// Check if the given file descriptor is considered a secure. +static bool is_file_secure(int fd, const char *filename) { + + int result; + struct stat statbuf; + + // Determine if the file is secure. + RESTARTABLE(::fstat(fd, &statbuf), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("fstat failed on %s: %s\n", filename, strerror(errno)); + } + return false; + } + if (statbuf.st_nlink > 1) { + // A file with multiple links is not expected. + if (PrintMiscellaneous && Verbose) { + warning("file %s has multiple links\n", filename); + } + return false; + } return true; } - -// return the user name for the given user id +// Return the user name for the given user id. // -// the caller is expected to free the allocated memory. -// +// The caller is expected to free the allocated memory. static char* get_user_name(uid_t uid) { struct passwd pwent; - // determine the max pwbuf size from sysconf, and hardcode + // Determine the max pwbuf size from sysconf, and hardcode // a default if this not available through sysconf. - // long bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize == -1) bufsize = 1024; @@ -344,7 +608,8 @@ strcat(usrdir_name, "/"); strcat(usrdir_name, dentry->d_name); - DIR* subdirp = os::opendir(usrdir_name); + // Open the user directory. + DIR* subdirp = open_directory_secure(usrdir_name); if (subdirp == NULL) { FREE_C_HEAP_ARRAY(char, usrdir_name); @@ -464,28 +729,7 @@ } } - -// remove file -// -// this method removes the file with the given file name in the -// named directory. -// -static void remove_file(const char* dirname, const char* filename) { - - size_t nbytes = strlen(dirname) + strlen(filename) + 2; - char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); - - strcpy(path, dirname); - strcat(path, "/"); - strcat(path, filename); - - remove_file(path); - - FREE_C_HEAP_ARRAY(char, path); -} - - -// cleanup stale shared memory resources +// Cleanup stale shared memory resources // // This method attempts to remove all stale shared memory files in // the named user temporary directory. It scans the named directory @@ -493,33 +737,26 @@ // process id is extracted from the file name and a test is run to // determine if the process is alive. If the process is not alive, // any stale file resources are removed. -// static void cleanup_sharedmem_resources(const char* dirname) { - // open the user temp directory - DIR* dirp = os::opendir(dirname); - + int saved_cwd_fd; + // Open the directory. + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); if (dirp == NULL) { - // directory doesn't exist, so there is nothing to cleanup + // Directory doesn't exist or is insecure, so there is nothing to cleanup. return; } - if (!is_directory_secure(dirname)) { - // the directory is not a secure directory - os::closedir(dirp); - return; - } - - // for each entry in the directory that matches the expected file + // For each entry in the directory that matches the expected file // name pattern, determine if the file resources are stale and if // so, remove the file resources. Note, instrumented HotSpot processes // for this user may start and/or terminate during this search and // remove or create new files in this directory. The behavior of this // loop under these conditions is dependent upon the implementation of // opendir/readdir. - // struct dirent* entry; char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal); + errno = 0; while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) { @@ -529,56 +766,55 @@ if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) { - // attempt to remove all unexpected files, except "." and ".." - remove_file(dirname, entry->d_name); + // Attempt to remove all unexpected files, except "." and "..". + unlink(entry->d_name); } errno = 0; continue; } - // we now have a file name that converts to a valid integer + // We now have a file name that converts to a valid integer // that could represent a process id . if this process id // matches the current process id or the process is not running, // then remove the stale file resources. // - // process liveness is detected by sending signal number 0 to + // Process liveness is detected by sending signal number 0 to // the process id (see kill(2)). if kill determines that the // process does not exist, then the file resources are removed. // if kill determines that that we don't have permission to // signal the process, then the file resources are assumed to // be stale and are removed because the resources for such a // process should be in a different user specific directory. - // if ((pid == os::current_process_id()) || (kill(pid, 0) == OS_ERR && (errno == ESRCH || errno == EPERM))) { - remove_file(dirname, entry->d_name); + unlink(entry->d_name); } errno = 0; } - os::closedir(dirp); - FREE_C_HEAP_ARRAY(char, dbuf); + + // Close the directory and reset the current working directory. + close_directory_secure_cwd(dirp, saved_cwd_fd); + + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); } -// make the user specific temporary directory. Returns true if +// Make the user specific temporary directory. Returns true if // the directory exists and is secure upon return. Returns false // if the directory exists but is either a symlink, is otherwise // insecure, or if an error occurred. -// static bool make_user_tmp_dir(const char* dirname) { - // create the directory with 0755 permissions. note that the directory + // Create the directory with 0755 permissions. note that the directory // will be owned by euid::egid, which may not be the same as uid::gid. - // if (mkdir(dirname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) == OS_ERR) { if (errno == EEXIST) { // The directory already exists and was probably created by another // JVM instance. However, this could also be the result of a // deliberate symlink. Verify that the existing directory is safe. - // if (!is_directory_secure(dirname)) { - // directory is not secure + // Directory is not secure. if (PrintMiscellaneous && Verbose) { warning("%s directory is insecure\n", dirname); } @@ -614,19 +850,63 @@ return -1; } + int saved_cwd_fd; + // Open the directory and set the current working directory to it. + DIR* dirp = open_directory_secure_cwd(dirname, &saved_cwd_fd); + if (dirp == NULL) { + // Directory doesn't exist or is insecure, so cannot create shared + // memory file. + return -1; + } + + // Open the filename in the current directory. + // Cannot use O_TRUNC here; truncation of an existing file has to happen + // after the is_file_secure() check below. int result; - RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE), result); + // No O_NOFOLLOW defined at buildtime, and it is not documented for open; + // so provide a workaround in this case. +#ifdef O_NOFOLLOW + RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); +#else + // workaround function (jdk6 code) + RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result); +#endif + if (result == OS_ERR) { if (PrintMiscellaneous && Verbose) { - warning("could not create file %s: %s\n", filename, strerror(errno)); + if (errno == ELOOP) { + warning("file %s is a symlink and is not secure\n", filename); + } else { + warning("could not create file %s: %s\n", filename, strerror(errno)); + } } + // Close the directory and reset the current working directory. + close_directory_secure_cwd(dirp, saved_cwd_fd); + return -1; } + // Close the directory and reset the current working directory. + close_directory_secure_cwd(dirp, saved_cwd_fd); // save the file descriptor int fd = result; + // Check to see if the file is secure. + if (!is_file_secure(fd, filename)) { + ::close(fd); + return -1; + } + + // Truncate the file to get rid of any existing data. + RESTARTABLE(::ftruncate(fd, (off_t)0), result); + if (result == OS_ERR) { + if (PrintMiscellaneous && Verbose) { + warning("could not truncate shared memory file: %s\n", strerror(errno)); + } + ::close(fd); + return -1; + } // set the file size RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { @@ -648,7 +928,14 @@ // open the file int result; + // No O_NOFOLLOW defined at buildtime, and it is not documented for open; + // so provide a workaround in this case +#ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); +#else + RESTARTABLE(::open_o_nofollow(filename, oflags), result); +#endif + if (result == OS_ERR) { if (errno == ENOENT) { THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), @@ -662,8 +949,15 @@ THROW_MSG_0(vmSymbols::java_io_IOException(), strerror(errno)); } } + int fd = result; - return result; + // Check to see if the file is secure. + if (!is_file_secure(fd, filename)) { + ::close(fd); + return -1; + } + + return fd; } // create a named shared memory region. returns the address of the @@ -695,13 +989,21 @@ char* dirname = get_user_tmp_dir(user_name); char* filename = get_sharedmem_filename(dirname, vmid); + // Get the short filename. + char* short_filename = strrchr(filename, '/'); + if (short_filename == NULL) { + short_filename = filename; + } else { + short_filename++; + } + // cleanup any stale shared memory files cleanup_sharedmem_resources(dirname); assert(((size > 0) && (size % os::vm_page_size() == 0)), "unexpected PerfMemory region size"); - fd = create_sharedmem_resources(dirname, filename, size); + fd = create_sharedmem_resources(dirname, short_filename, size); FREE_C_HEAP_ARRAY(char, user_name); FREE_C_HEAP_ARRAY(char, dirname); @@ -733,6 +1035,9 @@ // clear the shared memory region (void)::memset((void*) mapAddress, 0, size); + // It does not go through os api, the operation has to record from here. + MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal); + return mapAddress; } @@ -807,7 +1112,7 @@ char* mapAddress; int result; int fd; - size_t size; + size_t size = 0; const char* luser = NULL; int mmap_prot; @@ -819,12 +1124,18 @@ // constructs for the file and the shared memory mapping. if (mode == PerfMemory::PERF_MODE_RO) { mmap_prot = PROT_READ; + + // No O_NOFOLLOW defined at buildtime, and it is not documented for open. +#ifdef O_NOFOLLOW + file_flags = O_RDONLY | O_NOFOLLOW; +#else file_flags = O_RDONLY; +#endif } else if (mode == PerfMemory::PERF_MODE_RW) { #ifdef LATER mmap_prot = PROT_READ | PROT_WRITE; - file_flags = O_RDWR; + file_flags = O_RDWR | O_NOFOLLOW; #else THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Unsupported access mode"); @@ -853,9 +1164,9 @@ // store file, we don't follow them when attaching either. // if (!is_directory_secure(dirname)) { - FREE_C_HEAP_ARRAY(char, dirname); + FREE_C_HEAP_ARRAY(char, dirname, mtInternal); if (luser != user) { - FREE_C_HEAP_ARRAY(char, luser); + FREE_C_HEAP_ARRAY(char, luser, mtInternal); } THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Process not found"); @@ -901,6 +1212,9 @@ "Could not map PerfMemory"); } + // It does not go through os api, the operation has to record from here. + MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal); + *addr = mapAddress; *sizep = size;
--- a/hotspot/src/share/vm/code/codeCache.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -199,15 +199,10 @@ } guarantee(NonProfiledCodeHeapSize + ProfiledCodeHeapSize + NonNMethodCodeHeapSize <= ReservedCodeCacheSize, "Size check"); - // Align reserved sizes of CodeHeaps - size_t non_method_size = ReservedCodeSpace::allocation_align_size_up(NonNMethodCodeHeapSize); - size_t profiled_size = ReservedCodeSpace::allocation_align_size_up(ProfiledCodeHeapSize); - size_t non_profiled_size = ReservedCodeSpace::allocation_align_size_up(NonProfiledCodeHeapSize); - - // Compute initial sizes of CodeHeaps - size_t init_non_method_size = MIN2(InitialCodeCacheSize, non_method_size); - size_t init_profiled_size = MIN2(InitialCodeCacheSize, profiled_size); - size_t init_non_profiled_size = MIN2(InitialCodeCacheSize, non_profiled_size); + // Align CodeHeaps + size_t alignment = heap_alignment(); + size_t non_method_size = align_size_up(NonNMethodCodeHeapSize, alignment); + size_t profiled_size = align_size_down(ProfiledCodeHeapSize, alignment); // Reserve one continuous chunk of memory for CodeHeaps and split it into // parts for the individual heaps. The memory layout looks like this: @@ -216,18 +211,27 @@ // 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 @@ return NULL; } -void CodeCache::add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type) { +void CodeCache::add_heap(ReservedSpace rs, const char* name, int code_blob_type) { // Check if heap is needed if (!heap_available(code_blob_type)) { return; @@ -295,8 +299,8 @@ _heaps->append(heap); // Reserve Space + size_t size_initial = MIN2(InitialCodeCacheSize, rs.size()); size_initial = round_to(size_initial, os::vm_page_size()); - if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) { vm_exit_during_initialization("Could not reserve enough space for code cache"); } @@ -840,7 +844,7 @@ } else { // Use a single code heap ReservedCodeSpace rs = reserve_heap_memory(ReservedCodeCacheSize); - add_heap(rs, "CodeCache", InitialCodeCacheSize, CodeBlobType::All); + add_heap(rs, "CodeCache", CodeBlobType::All); } // Initialize ICache flush mechanism
--- a/hotspot/src/share/vm/code/codeCache.hpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Feb 04 18:22:46 2015 -0800 @@ -98,12 +98,13 @@ // CodeHeap management static void initialize_heaps(); // Initializes the CodeHeaps // Creates a new heap with the given name and size, containing CodeBlobs of the given type - static void add_heap(ReservedSpace rs, const char* name, size_t size_initial, int code_blob_type); + static void add_heap(ReservedSpace rs, const char* name, int code_blob_type); static CodeHeap* get_code_heap(const CodeBlob* cb); // Returns the CodeHeap for the given CodeBlob static CodeHeap* get_code_heap(int code_blob_type); // Returns the CodeHeap for the given CodeBlobType // Returns the name of the VM option to set the size of the corresponding CodeHeap static const char* get_code_heap_flag_name(int code_blob_type); static bool heap_available(int code_blob_type); // Returns true if an own CodeHeap for the given CodeBlobType is available + static size_t heap_alignment(); // Returns the alignment of the CodeHeaps in bytes static ReservedCodeSpace reserve_heap_memory(size_t size); // Reserves one continuous chunk of memory for the CodeHeaps // Iteration
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -553,7 +553,8 @@ int match = MethodMatcher::Exact; while (name[0] == '*') { match |= MethodMatcher::Suffix; - strcpy(name, name + 1); + // Copy remaining string plus NUL to the beginning + memmove(name, name + 1, strlen(name + 1) + 1); } if (strcmp(name, "*") == 0) return MethodMatcher::Any; @@ -689,6 +690,13 @@ return NULL; } +int skip_whitespace(char* line) { + // Skip any leading spaces + int whitespace_read = 0; + sscanf(line, "%*[ \t]%n", &whitespace_read); + return whitespace_read; +} + void CompilerOracle::parse_from_line(char* line) { if (line[0] == '\0') return; if (line[0] == '#') return; @@ -755,15 +763,9 @@ line += bytes_read; - // Skip any leading spaces before signature - int whitespace_read = 0; - sscanf(line, "%*[ \t]%n", &whitespace_read); - if (whitespace_read > 0) { - line += whitespace_read; - } - // there might be a signature following the method. // signatures always begin with ( so match that by hand + line += skip_whitespace(line); if (1 == sscanf(line, "(%254[[);/" RANGEBASE "]%n", sig + 1, &bytes_read)) { sig[0] = '('; line += bytes_read; @@ -786,7 +788,9 @@ // // For future extensions: extend scan_flag_and_value() char option[256]; // stores flag for Type (1) and type of Type (2) - while (sscanf(line, "%*[ \t]%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { + + line += skip_whitespace(line); + while (sscanf(line, "%255[a-zA-Z0-9]%n", option, &bytes_read) == 1) { if (match != NULL && !_quiet) { // Print out the last match added ttyLocker ttyl; @@ -816,6 +820,7 @@ // Type (1) option match = add_option_string(c_name, c_match, m_name, m_match, signature, option, true); } + line += skip_whitespace(line); } // while( } else { match = add_predicate(command, c_name, c_match, m_name, m_match, signature);
--- a/hotspot/src/share/vm/opto/library_call.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1351,7 +1351,6 @@ Node* cache = __ ConI(cache_i); Node* md2 = __ ConI(md2_i); Node* lastChar = __ ConI(target_array->char_at(target_length - 1)); - Node* targetCount = __ ConI(target_length); Node* targetCountLess1 = __ ConI(target_length - 1); Node* targetOffset = __ ConI(targetOffset_i); Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1); @@ -1408,8 +1407,6 @@ Node* arg = argument(1); Node* result; - // Disable the use of pcmpestri until it can be guaranteed that - // the load doesn't cross into the uncommited space. if (Matcher::has_match_rule(Op_StrIndexOf) && UseSSE42Intrinsics) { // Generate SSE4.2 version of indexOf @@ -1421,9 +1418,6 @@ return true; } - ciInstanceKlass* str_klass = env()->String_klass(); - const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(str_klass); - // Make the merge point RegionNode* result_rgn = new RegionNode(4); Node* result_phi = new PhiNode(result_rgn, TypeInt::INT);
--- a/hotspot/src/share/vm/opto/output.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/opto/output.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -2475,7 +2475,7 @@ if( iop == Op_Con ) continue; // Do not schedule Top if( iop == Op_Node && // Do not schedule PhiNodes, ProjNodes mach->pipeline() == MachNode::pipeline_class() && - !n->is_SpillCopy() ) // Breakpoints, Prolog, etc + !n->is_SpillCopy() && !n->is_MachMerge() ) // Breakpoints, Prolog, etc continue; break; // Funny loop structure to be sure... }
--- a/hotspot/src/share/vm/opto/postaloc.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/opto/postaloc.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -428,6 +428,7 @@ // 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);
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Feb 04 18:22:46 2015 -0800 @@ -1127,7 +1127,7 @@ #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 @@ // 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 @@ 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); }
--- a/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/arguments/CheckCompileThresholdScaling.java Wed Feb 04 18:22:46 2015 -0800 @@ -87,6 +87,13 @@ { "-XX:-TieredCompilation", "-XX:+PrintFlagsFinal", + "-XX:CompileThreshold=1000", + "-XX:CompileThresholdScaling=0.0", + "-version" + }, + { + "-XX:-TieredCompilation", + "-XX:+PrintFlagsFinal", "-XX:CompileThreshold=0", "-XX:CompileThresholdScaling=0.75", "-version" @@ -108,6 +115,11 @@ "double CompileThresholdScaling := 0.750000 {product}" }, { + "intx CompileThreshold := 1000 {pd product}", + "double CompileThresholdScaling := 0.000000 {product}", + "interpreted mode" + }, + { "intx CompileThreshold := 0 {pd product}", "double CompileThresholdScaling := 0.750000 {product}", "interpreted mode" @@ -295,21 +307,21 @@ "double CompileThresholdScaling := 2.000000 {product}" }, { - "intx Tier0BackedgeNotifyFreqLog := 0 {product}", - "intx Tier0InvokeNotifyFreqLog := 0 {product}", - "intx Tier23InlineeNotifyFreqLog := 0 {product}", - "intx Tier2BackedgeNotifyFreqLog := 0 {product}", - "intx Tier2InvokeNotifyFreqLog := 0 {product}", - "intx Tier3BackEdgeThreshold := 0 {product}", - "intx Tier3BackedgeNotifyFreqLog := 0 {product}", - "intx Tier3CompileThreshold := 0 {product}", - "intx Tier3InvocationThreshold := 0 {product}", - "intx Tier3InvokeNotifyFreqLog := 0 {product}", - "intx Tier3MinInvocationThreshold := 0 {product}", - "intx Tier4BackEdgeThreshold := 0 {product}", - "intx Tier4CompileThreshold := 0 {product}", - "intx Tier4InvocationThreshold := 0 {product}", - "intx Tier4MinInvocationThreshold := 0 {product}", + "intx Tier0BackedgeNotifyFreqLog := 10 {product}", + "intx Tier0InvokeNotifyFreqLog := 7 {product}", + "intx Tier23InlineeNotifyFreqLog := 20 {product}", + "intx Tier2BackedgeNotifyFreqLog := 14 {product}", + "intx Tier2InvokeNotifyFreqLog := 11 {product}", + "intx Tier3BackEdgeThreshold := 60000 {product}", + "intx Tier3BackedgeNotifyFreqLog := 13 {product}", + "intx Tier3CompileThreshold := 2000 {product}", + "intx Tier3InvocationThreshold := 200 {product}", + "intx Tier3InvokeNotifyFreqLog := 10 {product}", + "intx Tier3MinInvocationThreshold := 100 {product}", + "intx Tier4BackEdgeThreshold := 40000 {product}", + "intx Tier4CompileThreshold := 15000 {product}", + "intx Tier4InvocationThreshold := 5000 {product}", + "intx Tier4MinInvocationThreshold := 600 {product}", "double CompileThresholdScaling := 0.000000 {product}", "interpreted mode" }
--- a/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/codecache/cli/printcodecache/PrintCodeCacheRunner.java Wed Feb 04 18:22:46 2015 -0800 @@ -82,6 +82,9 @@ ExitCode.OK, testCaseDescription.getTestOptions(options, CommandLineOptionTest.prepareBooleanFlag( - "PrintCodeCache", printCodeCache))); + "PrintCodeCache", printCodeCache), + // Do not use large pages to avoid large page + // alignment of code heaps affecting their size. + "-XX:-UseLargePages")); } }
--- a/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/codecache/stress/CodeCacheStressRunner.java Wed Feb 04 18:22:46 2015 -0800 @@ -36,7 +36,7 @@ try { // adjust timeout and substract vm init and exit time long timeout = Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT); - timeout *= 0.9; + timeout *= 0.8; new TimeLimitedRunner(timeout, 2.0d, this::test).call(); } catch (Exception e) { throw new Error("Exception occurred during test execution", e);
--- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -77,7 +77,7 @@ } public OverloadCompileQueueTest() { - Helper.startInfiniteLoopThread(this::lockUnlock); + Helper.startInfiniteLoopThread(this::lockUnlock, 100L); } @Override @@ -99,8 +99,9 @@ private void lockUnlock() { try { + int sleep = Helper.RNG.nextInt(MAX_SLEEP); Helper.WHITE_BOX.lockCompilation(); - Thread.sleep(Helper.RNG.nextInt(MAX_SLEEP)); + Thread.sleep(sleep); } catch (InterruptedException e) { throw new Error("TESTBUG: lockUnlocker thread was unexpectedly interrupted", e); } finally {
--- a/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/oracle/CheckCompileCommandOption.java Wed Feb 04 18:22:46 2015 -0800 @@ -21,12 +21,15 @@ * questions. */ +import java.io.PrintWriter; +import java.io.File; + import com.oracle.java.testlibrary.*; /* * @test CheckCompileCommandOption - * @bug 8055286 8056964 8059847 - * @summary "Checks parsing of -XX:+CompileCommand=option" + * @bug 8055286 8056964 8059847 8069035 + * @summary "Checks parsing of -XX:CompileCommand=option" * @library /testlibrary * @run main CheckCompileCommandOption */ @@ -45,38 +48,69 @@ // have the the following types: intx, uintx, bool, ccstr, // ccstrlist, and double. + private static final String[][] FILE_ARGUMENTS = { + { + "-XX:CompileCommandFile=" + new File(System.getProperty("test.src", "."), "command1.txt"), + "-version" + }, + { + "-XX:CompileCommandFile=" + new File(System.getProperty("test.src", "."), "command2.txt"), + "-version" + } + }; + + private static final String[][] FILE_EXPECTED_OUTPUT = { + { + "CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption4 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption9 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption10 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption11 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption12 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption13 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption14 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption15 = true", + "CompileCommand: option com/oracle/Test.test(I) bool MyBoolOption16 = true" + }, + { + "CompileCommand: option Test.test const char* MyListOption = '_foo _bar'", + "CompileCommand: option Test.test const char* MyStrOption = '_foo'", + "CompileCommand: option Test.test bool MyBoolOption = false", + "CompileCommand: option Test.test intx MyIntxOption = -1", + "CompileCommand: option Test.test uintx MyUintxOption = 1", + "CompileCommand: option Test.test bool MyFlag = true", + "CompileCommand: option Test.test double MyDoubleOption = 1.123000" + } + }; + private static final String[][] TYPE_1_ARGUMENTS = { { "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1", "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption2", "-XX:CompileCommand=option,com.oracle.Test::test,MyBoolOption3", "-XX:CompileCommand=option,com/oracle/Test::test,MyBoolOption4", - "-version" - }, - { - "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption1,MyBoolOption2", - "-version" - }, - { - "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption1,MyBoolOption2", + "-XX:CompileCommand=option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6", + "-XX:CompileCommand=option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8", "-version" } }; private static final String[][] TYPE_1_EXPECTED_OUTPUTS = { { - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true", - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true", - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption3 = true", - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption4 = true" - }, - { - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true", - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true", - }, - { - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption1 = true", - "CompilerOracle: option com/oracle/Test.test bool MyBoolOption2 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption1 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption2 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption3 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption4 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption5 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption6 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption7 = true", + "CompileCommand: option com/oracle/Test.test bool MyBoolOption8 = true" } }; @@ -88,38 +122,28 @@ "-XX:CompileCommand=option,Test::test,intx,MyIntxOption,-1", "-XX:CompileCommand=option,Test::test,uintx,MyUintxOption,1", "-XX:CompileCommand=option,Test::test,MyFlag", - "-XX:CompileCommand=option,Test::test,double,MyDoubleOption,1.123", - "-version" - }, - { - "-XX:CompileCommand=option,Test.test,double,MyDoubleOption,1.123", - "-version" - }, - { - "-XX:CompileCommand=option,Test::test,bool,MyBoolOption,false,intx,MyIntxOption,-1,uintx,MyUintxOption,1,MyFlag,double,MyDoubleOption,1.123", + "-XX:CompileCommand=option,Test::test,double,MyDoubleOption1,1.123", + "-XX:CompileCommand=option,Test.test,double,MyDoubleOption2,1.123", + "-XX:CompileCommand=option,Test::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123", "-version" } }; private static final String[][] TYPE_2_EXPECTED_OUTPUTS = { { - "CompilerOracle: option Test.test const char* MyListOption = '_foo _bar'", - "CompilerOracle: option Test.test const char* MyStrOption = '_foo'", - "CompilerOracle: option Test.test bool MyBoolOption = false", - "CompilerOracle: option Test.test intx MyIntxOption = -1", - "CompilerOracle: option Test.test uintx MyUintxOption = 1", - "CompilerOracle: option Test.test bool MyFlag = true", - "CompilerOracle: option Test.test double MyDoubleOption = 1.123000" - }, - { - "CompilerOracle: option Test.test double MyDoubleOption = 1.123000" - }, - { - "CompilerOracle: option Test.test bool MyBoolOption = false", - "CompilerOracle: option Test.test intx MyIntxOption = -1", - "CompilerOracle: option Test.test uintx MyUintxOption = 1", - "CompilerOracle: option Test.test bool MyFlag = true", - "CompilerOracle: option Test.test double MyDoubleOption = 1.123000", + "CompileCommand: option Test.test const char* MyListOption = '_foo _bar'", + "CompileCommand: option Test.test const char* MyStrOption = '_foo'", + "CompileCommand: option Test.test bool MyBoolOption = false", + "CompileCommand: option Test.test intx MyIntxOption = -1", + "CompileCommand: option Test.test uintx MyUintxOption = 1", + "CompileCommand: option Test.test bool MyFlag = true", + "CompileCommand: option Test.test double MyDoubleOption1 = 1.123000", + "CompileCommand: option Test.test double MyDoubleOption2 = 1.123000", + "CompileCommand: option Test.test bool MyBoolOptionX = false", + "CompileCommand: option Test.test intx MyIntxOptionX = -1", + "CompileCommand: option Test.test uintx MyUintxOptionX = 1", + "CompileCommand: option Test.test bool MyFlagX = true", + "CompileCommand: option Test.test double MyDoubleOptionX = 1.123000", } }; @@ -172,7 +196,7 @@ out.shouldContain(expected_output); } - out.shouldNotContain("CompileCommand: unrecognized line"); + out.shouldNotContain("CompileCommand: An error occured during parsing"); out.shouldHaveExitValue(0); } @@ -183,7 +207,7 @@ pb = ProcessTools.createJavaProcessBuilder(arguments); out = new OutputAnalyzer(pb.start()); - out.shouldContain("CompileCommand: unrecognized line"); + out.shouldContain("CompileCommand: An error occured during parsing"); out.shouldHaveExitValue(0); } @@ -212,5 +236,10 @@ for (String[] arguments: TYPE_2_INVALID_ARGUMENTS) { verifyInvalidOption(arguments); } + + // Check if commands in command file are parsed correctly + for (int i = 0; i < FILE_ARGUMENTS.length; i++) { + verifyValidOption(FILE_ARGUMENTS[i], FILE_EXPECTED_OUTPUT[i]); + } } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/oracle/TestCompileCommand.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.PrintWriter; +import java.io.File; + +import com.oracle.java.testlibrary.*; + +/* + * @test TestCompileCommand + * @bug 8069389 + * @summary "Regression tests of -XX:CompileCommand" + * @library /testlibrary + * @run main TestCompileCommand + */ + +public class TestCompileCommand { + + private static final String[][] ARGUMENTS = { + { + "-XX:CompileCommand=print,*01234567890123456789012345678901234567890123456789,*0123456789012345678901234567890123456789", + "-version" + } + }; + + private static final String[][] OUTPUTS = { + { + "print *01234567890123456789012345678901234567890123456789.*0123456789012345678901234567890123456789" + } + }; + + private static void verifyValidOption(String[] arguments, String[] expected_outputs) throws Exception { + ProcessBuilder pb; + OutputAnalyzer out; + + pb = ProcessTools.createJavaProcessBuilder(arguments); + out = new OutputAnalyzer(pb.start()); + + for (String expected_output : expected_outputs) { + out.shouldContain(expected_output); + } + + out.shouldNotContain("CompileCommand: An error occured during parsing"); + out.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + + if (ARGUMENTS.length != OUTPUTS.length) { + throw new RuntimeException("Test is set up incorrectly: length of arguments and expected outputs for type (1) options does not match."); + } + + // Check if type (1) options are parsed correctly + for (int i = 0; i < ARGUMENTS.length; i++) { + verifyValidOption(ARGUMENTS[i], OUTPUTS[i]); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/oracle/command1.txt Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,12 @@ +option,com/oracle/Test.test,MyBoolOption1 +option,com/oracle/Test,test,MyBoolOption2 +option,com.oracle.Test::test,MyBoolOption3 +option,com/oracle/Test::test,MyBoolOption4 +option,com/oracle/Test.test,MyBoolOption5,MyBoolOption6 +option,com/oracle/Test,test,MyBoolOption7,MyBoolOption8 +option,com/oracle/Test.test(I),MyBoolOption9 +option,com/oracle/Test,test,(I),MyBoolOption10 +option,com.oracle.Test::test(I),MyBoolOption11 +option,com/oracle/Test::test(I),MyBoolOption12 +option,com/oracle/Test.test(I),MyBoolOption13,MyBoolOption14 +option,com/oracle/Test,test(I),MyBoolOption15,MyBoolOption16
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/hotspot/test/compiler/oracle/command2.txt Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,7 @@ +option,Test::test,ccstrlist,MyListOption,_foo,_bar +option,Test::test,ccstr,MyStrOption,_foo +option,Test::test,bool,MyBoolOption,false +option,Test::test,intx,MyIntxOption,-1 +option,Test::test,uintx,MyUintxOption,1 +option,Test::test,MyFlag +option,Test::test,double,MyDoubleOption,1.123
--- a/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/rtm/locking/TestRTMTotalCountIncrRate.java Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -119,13 +119,13 @@ return new String[] { getMethodWithLockName() }; } - public void lock(booleab forceAbort) { + public void lock(boolean forceAbort) { synchronized(monitor) { if (forceAbort) { // We're calling native method in order to force // abort. It's done by explicit xabort call emitted // in SharedRuntime::generate_native_wrapper. - // If an actuall JNI call will be replaced by + // If an actual JNI call will be replaced by // intrinsic - we'll be in trouble, since xabort // will be no longer called and test may fail. UNSAFE.addressSize();
--- a/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Tue Feb 03 12:49:33 2015 +0100 +++ b/hotspot/test/compiler/whitebox/ForceNMethodSweepTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -34,7 +34,6 @@ /* * @test * @bug 8059624 8064669 - * @ignore 8066998 * @library /testlibrary /../../test/lib * @build ForceNMethodSweepTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -42,7 +41,7 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:-TieredCompilation -XX:+WhiteBoxAPI * -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* - * ForceNMethodSweepTest + * -XX:-BackgroundCompilation ForceNMethodSweepTest * @summary testing of WB::forceNMethodSweep */ public class ForceNMethodSweepTest extends CompilerWhiteBoxTest {
--- a/jaxp/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -290,3 +290,4 @@ 0dab3e848229127c7aca4c58b98e2d90ba70372f jdk9-b45 74eaf7ad986576c792df4dbff05eed63e5727695 jdk9-b46 e391de88e69b59d7c618387e3cf91032f6991ce9 jdk9-b47 +833051855168a973780fafeb6fc59e7370bcf400 jdk9-b48
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/runtime/BasisLibrary.java Wed Feb 04 18:22:46 2015 -0800 @@ -270,8 +270,8 @@ if (Double.isNaN(start)) return(EMPTYSTRING); - final int strlen = value.length(); - int istart = (int)Math.round(start) - 1; + final int strlen = value.length(); + int istart = (int)Math.round(start) - 1; if (istart > strlen) return(EMPTYSTRING); @@ -292,10 +292,11 @@ public static String substringF(String value, double start, double length) { if (Double.isInfinite(start) || Double.isNaN(start) || - Double.isNaN(length)) + Double.isNaN(length) || + length < 0) return(EMPTYSTRING); - int istart = (int)Math.round(start) - 1; + int istart = (int)Math.round(start) - 1; final int isum; if (Double.isInfinite(length)) isum = Integer.MAX_VALUE;
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathExpressionImpl.java Wed Feb 04 18:22:46 2015 -0800 @@ -1,15 +1,15 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright 1999-2004 The Apache Software Foundation. + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -17,36 +17,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// $Id: XPathExpressionImpl.java,v 1.3 2005/09/27 09:40:43 sunithareddy Exp $ package com.sun.org.apache.xpath.internal.jaxp; -import com.sun.org.apache.xpath.internal.*; -import javax.xml.transform.TransformerException; - +import com.sun.org.apache.xalan.internal.utils.FeatureManager; import com.sun.org.apache.xpath.internal.objects.XObject; -import com.sun.org.apache.xml.internal.dtm.DTM; -import com.sun.org.apache.xml.internal.utils.PrefixResolver; -import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; -import com.sun.org.apache.xalan.internal.res.XSLMessages; -import com.sun.org.apache.xalan.internal.utils.FactoryImpl; -import com.sun.org.apache.xalan.internal.utils.FeatureManager; - -import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathEvaluationResult; +import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; -import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFunctionResolver; import javax.xml.xpath.XPathVariableResolver; -import javax.xml.xpath.XPathConstants; - +import org.w3c.dom.Document; import org.w3c.dom.Node; -import org.w3c.dom.Document; -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.traversal.NodeIterator; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.DocumentBuilder; - import org.xml.sax.InputSource; /** @@ -54,21 +39,9 @@ * * @author Ramesh Mandava */ -public class XPathExpressionImpl implements javax.xml.xpath.XPathExpression{ - - private XPathFunctionResolver functionResolver; - private XPathVariableResolver variableResolver; - private JAXPPrefixResolver prefixResolver; - private com.sun.org.apache.xpath.internal.XPath xpath; +public class XPathExpressionImpl extends XPathImplUtil implements XPathExpression { - // By default Extension Functions are allowed in XPath Expressions. If - // Secure Processing Feature is set on XPathFactory then the invocation of - // extensions function need to throw XPathFunctionException - private boolean featureSecureProcessing = false; - - private boolean useServicesMechanism = true; - - private final FeatureManager featureManager; + private com.sun.org.apache.xpath.internal.XPath xpath; /** Protected constructor to prevent direct instantiation; use compile() * from the context. @@ -81,7 +54,7 @@ protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath, JAXPPrefixResolver prefixResolver, XPathFunctionResolver functionResolver, - XPathVariableResolver variableResolver ) { + XPathVariableResolver variableResolver) { this(xpath, prefixResolver, functionResolver, variableResolver, false, true, new FeatureManager()); }; @@ -89,291 +62,108 @@ protected XPathExpressionImpl(com.sun.org.apache.xpath.internal.XPath xpath, JAXPPrefixResolver prefixResolver,XPathFunctionResolver functionResolver, XPathVariableResolver variableResolver, boolean featureSecureProcessing, - boolean useServicesMechanism, FeatureManager featureManager ) { + boolean useServiceMechanism, FeatureManager featureManager) { this.xpath = xpath; this.prefixResolver = prefixResolver; this.functionResolver = functionResolver; this.variableResolver = variableResolver; this.featureSecureProcessing = featureSecureProcessing; - this.useServicesMechanism = useServicesMechanism; + this.useServiceMechanism = useServiceMechanism; this.featureManager = featureManager; }; - public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath ) { + public void setXPath (com.sun.org.apache.xpath.internal.XPath xpath) { this.xpath = xpath; } public Object eval(Object item, QName returnType) throws javax.xml.transform.TransformerException { - XObject resultObject = eval ( item ); - return getResultAsType( resultObject, returnType ); - } - - private XObject eval ( Object contextItem ) - throws javax.xml.transform.TransformerException { - com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null; - if ( functionResolver != null ) { - JAXPExtensionsProvider jep = new JAXPExtensionsProvider( - functionResolver, featureSecureProcessing, featureManager ); - xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep ); - } else { - xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); - } - - xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); - XObject xobj = null; - - Node contextNode = (Node)contextItem; - // We always need to have a ContextNode with Xalan XPath implementation - // To allow simple expression evaluation like 1+1 we are setting - // dummy Document as Context Node - - if ( contextNode == null ) - xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver); - else - xobj = xpath.execute(xpathSupport, contextNode, prefixResolver); - - return xobj; + XObject resultObject = eval(item, xpath); + return getResultAsType(resultObject, returnType); } - - /** - * <p>Evaluate the compiled XPath expression in the specified context and - * return the result as the specified type.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>returnType</code> is not one of the types defined - * in {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>returnType</code> is <code>null</code>, then a - * <code>NullPointerException</code> is thrown.</p> - * - * @param item The starting context (node or node list, for example). - * @param returnType The desired return type. - * - * @return The <code>Object</code> that is the result of evaluating the - * expression and converting the result to - * <code>returnType</code>. - * - * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one - * of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>returnType</code> is - * <code>null</code>. - */ + @Override public Object evaluate(Object item, QName returnType) throws XPathExpressionException { - //Validating parameters to enforce constraints defined by JAXP spec - if ( returnType == null ) { - //Throwing NullPointerException as defined in spec - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"returnType"} ); - throw new NullPointerException( fmsg ); - } - // Checking if requested returnType is supported. returnType need to be - // defined in XPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); - } + isSupported(returnType); try { - return eval( item, returnType); - } catch ( java.lang.NullPointerException npe ) { + return eval(item, returnType); + } catch (java.lang.NullPointerException npe) { // If VariableResolver returns null Or if we get // NullPointerException at this stage for some other reason // then we have to reurn XPathException - throw new XPathExpressionException ( npe ); - } catch ( javax.xml.transform.TransformerException te ) { + throw new XPathExpressionException (npe); + } catch (javax.xml.transform.TransformerException te) { Throwable nestedException = te.getException(); - if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { + if (nestedException instanceof javax.xml.xpath.XPathFunctionException) { throw (javax.xml.xpath.XPathFunctionException)nestedException; } else { // For any other exceptions we need to throw - // XPathExpressionException ( as per spec ) - throw new XPathExpressionException( te); + // XPathExpressionException (as per spec) + throw new XPathExpressionException(te); } } - - } - - /** - * <p>Evaluate the compiled XPath expression in the specified context and - * return the result as a <code>String</code>.</p> - * - * <p>This method calls {@link #evaluate(Object item, QName returnType)} - * with a <code>returnType</code> of - * {@link XPathConstants#STRING}.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * - * @param item The starting context (node or node list, for example). - * - * @return The <code>String</code> that is the result of evaluating the - * expression and converting the result to a - * <code>String</code>. - * - * @throws XPathExpressionException If the expression cannot be evaluated. - */ - public String evaluate(Object item) - throws XPathExpressionException { - return (String)this.evaluate( item, XPathConstants.STRING ); } - - static DocumentBuilderFactory dbf = null; - static DocumentBuilder db = null; - static Document d = null; + @Override + public String evaluate(Object item) + throws XPathExpressionException { + return (String)this.evaluate(item, XPathConstants.STRING); + } - /** - * <p>Evaluate the compiled XPath expression in the context of the - * specified <code>InputSource</code> and return the result as the - * specified type.</p> - * - * <p>This method builds a data model for the {@link InputSource} and calls - * {@link #evaluate(Object item, QName returnType)} on the resulting - * document object.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>returnType</code> is not one of the types defined in - * {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - *<p>If <code>source</code> or <code>returnType</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> - * - * @param source The <code>InputSource</code> of the document to evaluate - * over. - * @param returnType The desired return type. - * - * @return The <code>Object</code> that is the result of evaluating the - * expression and converting the result to - * <code>returnType</code>. - * - * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one - * of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>source</code> or - * <code>returnType</code> is <code>null</code>. - */ + @Override public Object evaluate(InputSource source, QName returnType) throws XPathExpressionException { - if ( ( source == null ) || ( returnType == null ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, - null ); - throw new NullPointerException ( fmsg ); - } - // Checking if requested returnType is supported. returnType need to be - // defined in XPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); - } + isSupported (returnType); try { - if ( dbf == null ) { - dbf = FactoryImpl.getDOMFactory(useServicesMechanism); - dbf.setNamespaceAware( true ); - dbf.setValidating( false ); - } - db = dbf.newDocumentBuilder(); - Document document = db.parse( source ); - return eval( document, returnType ); - } catch ( Exception e ) { - throw new XPathExpressionException ( e ); + Document document = getDocument(source); + return eval(document, returnType); + } catch (TransformerException e) { + throw new XPathExpressionException(e); } } - /** - * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a - * <code>String</code>.</p> - * - * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of - * {@link XPathConstants#STRING}.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> - * - * @param source The <code>InputSource</code> of the document to evaluate over. - * - * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a - * <code>String</code>. - * - * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws NullPointerException If <code>source</code> is <code>null</code>. - */ + @Override public String evaluate(InputSource source) throws XPathExpressionException { - return (String)this.evaluate( source, XPathConstants.STRING ); + return (String)this.evaluate(source, XPathConstants.STRING); } - private boolean isSupported( QName returnType ) { - // XPathConstants.STRING - if ( ( returnType.equals( XPathConstants.STRING ) ) || - ( returnType.equals( XPathConstants.NUMBER ) ) || - ( returnType.equals( XPathConstants.BOOLEAN ) ) || - ( returnType.equals( XPathConstants.NODE ) ) || - ( returnType.equals( XPathConstants.NODESET ) ) ) { + @Override + public <T>T evaluateExpression(Object item, Class<T> type) + throws XPathExpressionException { + isSupportedClassType(type); - return true; - } - return false; - } + try { + XObject resultObject = eval(item, xpath); + if (type.isAssignableFrom(XPathEvaluationResult.class)) { + return getXPathResult(resultObject, type); + } else { + return XPathResultImpl.getValue(resultObject, type); + } - private Object getResultAsType( XObject resultObject, QName returnType ) - throws javax.xml.transform.TransformerException { - // XPathConstants.STRING - if ( returnType.equals( XPathConstants.STRING ) ) { - return resultObject.str(); + } catch (javax.xml.transform.TransformerException te) { + throw new XPathExpressionException(te); } - // XPathConstants.NUMBER - if ( returnType.equals( XPathConstants.NUMBER ) ) { - return new Double ( resultObject.num()); - } - // XPathConstants.BOOLEAN - if ( returnType.equals( XPathConstants.BOOLEAN ) ) { - return new Boolean( resultObject.bool()); - } - // XPathConstants.NODESET ---ORdered, UNOrdered??? - if ( returnType.equals( XPathConstants.NODESET ) ) { - return resultObject.nodelist(); - } - // XPathConstants.NODE - if ( returnType.equals( XPathConstants.NODE ) ) { - NodeIterator ni = resultObject.nodeset(); - //Return the first node, or null - return ni.nextNode(); - } - // If isSupported check is already done then the execution path - // shouldn't come here. Being defensive - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString()}); - throw new IllegalArgumentException ( fmsg ); } + @Override + public XPathEvaluationResult<?> evaluateExpression(Object item) + throws XPathExpressionException { + return evaluateExpression(item, XPathEvaluationResult.class); + } + + @Override + public <T>T evaluateExpression(InputSource source, Class<T> type) + throws XPathExpressionException { + Document document = getDocument(source); + return evaluateExpression(document, type); + } + + @Override + public XPathEvaluationResult<?> evaluateExpression(InputSource source) + throws XPathExpressionException { + return evaluateExpression(source, XPathEvaluationResult.class); + } }
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java Wed Feb 04 18:22:46 2015 -0800 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 1999-2004 The Apache Software Foundation. @@ -28,55 +27,37 @@ import javax.xml.xpath.XPathFunctionResolver; import javax.xml.xpath.XPathVariableResolver; import javax.xml.xpath.XPathExpression; - -import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xpath.internal.*; import com.sun.org.apache.xpath.internal.objects.XObject; -import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; -import com.sun.org.apache.xalan.internal.res.XSLMessages; -import com.sun.org.apache.xalan.internal.utils.FactoryImpl; import com.sun.org.apache.xalan.internal.utils.FeatureManager; - -import org.w3c.dom.Node; import org.w3c.dom.Document; -import org.w3c.dom.traversal.NodeIterator; - import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import javax.xml.parsers.*; - -import java.io.IOException; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathEvaluationResult; /** * The XPathImpl class provides implementation for the methods defined in - * javax.xml.xpath.XPath interface. This provide simple access to the results + * javax.xml.xpath.XPath interface. This provides simple access to the results * of an XPath expression. * - * * @author Ramesh Mandava + * + * Updated 12/04/2014: + * New methods: evaluateExpression + * Refactored to share code with XPathExpressionImpl. */ -public class XPathImpl implements javax.xml.xpath.XPath { +public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { // Private variables - private XPathVariableResolver variableResolver; - private XPathFunctionResolver functionResolver; private XPathVariableResolver origVariableResolver; private XPathFunctionResolver origFunctionResolver; private NamespaceContext namespaceContext=null; - private JAXPPrefixResolver prefixResolver; - // By default Extension Functions are allowed in XPath Expressions. If - // Secure Processing Feature is set on XPathFactory then the invocation of - // extensions function need to throw XPathFunctionException - private boolean featureSecureProcessing = false; - private boolean useServiceMechanism = true; - private final FeatureManager featureManager; - XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr ) { + XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { this(vr, fr, false, true, new FeatureManager()); } - XPathImpl( XPathVariableResolver vr, XPathFunctionResolver fr, + XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing, boolean useServiceMechanism, FeatureManager featureManager) { this.origVariableResolver = this.variableResolver = vr; @@ -86,451 +67,173 @@ this.featureManager = featureManager; } - /** - * <p>Establishes a variable resolver.</p> - * - * @param resolver Variable Resolver - */ + + //-Override- public void setXPathVariableResolver(XPathVariableResolver resolver) { - if ( resolver == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPathVariableResolver"} ); - throw new NullPointerException( fmsg ); - } + requireNonNull(resolver, "XPathVariableResolver"); this.variableResolver = resolver; } - /** - * <p>Returns the current variable resolver.</p> - * - * @return Current variable resolver - */ + //-Override- public XPathVariableResolver getXPathVariableResolver() { return variableResolver; } - /** - * <p>Establishes a function resolver.</p> - * - * @param resolver XPath function resolver - */ + //-Override- public void setXPathFunctionResolver(XPathFunctionResolver resolver) { - if ( resolver == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPathFunctionResolver"} ); - throw new NullPointerException( fmsg ); - } + requireNonNull(resolver, "XPathFunctionResolver"); this.functionResolver = resolver; } - /** - * <p>Returns the current function resolver.</p> - * - * @return Current function resolver - */ + //-Override- public XPathFunctionResolver getXPathFunctionResolver() { return functionResolver; } - /** - * <p>Establishes a namespace context.</p> - * - * @param nsContext Namespace context to use - */ + //-Override- public void setNamespaceContext(NamespaceContext nsContext) { - if ( nsContext == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"NamespaceContext"} ); - throw new NullPointerException( fmsg ); - } + requireNonNull(nsContext, "NamespaceContext"); this.namespaceContext = nsContext; - this.prefixResolver = new JAXPPrefixResolver ( nsContext ); + this.prefixResolver = new JAXPPrefixResolver (nsContext); } - /** - * <p>Returns the current namespace context.</p> - * - * @return Current Namespace context - */ + //-Override- public NamespaceContext getNamespaceContext() { return namespaceContext; } - private static Document d = null; - - private DocumentBuilder getParser() { - try { - // we'd really like to cache those DocumentBuilders, but we can't because: - // 1. thread safety. parsers are not thread-safe, so at least - // we need one instance per a thread. - // 2. parsers are non-reentrant, so now we are looking at having a - // pool of parsers. - // 3. then the class loading issue. The look-up procedure of - // DocumentBuilderFactory.newInstance() depends on context class loader - // and system properties, which may change during the execution of JVM. - // - // so we really have to create a fresh DocumentBuilder every time we need one - // - KK - DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism); - dbf.setNamespaceAware( true ); - dbf.setValidating( false ); - return dbf.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - // this should never happen with a well-behaving JAXP implementation. - throw new Error(e); - } - } - + /** + * Evaluate an {@code XPath} expression in the specified context. + * @param expression The XPath expression. + * @param contextItem The starting context. + * @return an XObject as the result of evaluating the expression + * @throws TransformerException if evaluating fails + */ + private XObject eval(String expression, Object contextItem) + throws TransformerException { + requireNonNull(expression, "XPath expression"); + com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath(expression, + null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); - private XObject eval(String expression, Object contextItem) - throws javax.xml.transform.TransformerException { - com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression, - null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); - com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null; - if ( functionResolver != null ) { - JAXPExtensionsProvider jep = new JAXPExtensionsProvider( - functionResolver, featureSecureProcessing, featureManager ); - xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep ); - } else { - xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); - } - - XObject xobj = null; - - xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); - - // If item is null, then we will create a a Dummy contextNode - if ( contextItem instanceof Node ) { - xobj = xpath.execute (xpathSupport, (Node)contextItem, - prefixResolver ); - } else { - xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver ); - } - - return xobj; + return eval(contextItem, xpath); } - /** - * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and <code>QName</code> resolution and return type conversion.</p> - * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} ( - * {@link XPathConstants#NUMBER NUMBER}, - * {@link XPathConstants#STRING STRING}, - * {@link XPathConstants#BOOLEAN BOOLEAN}, - * {@link XPathConstants#NODE NODE} or - * {@link XPathConstants#NODESET NODESET}) - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a - * <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * @param item The starting context (node or node list, for example). - * @param returnType The desired return type. - * - * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>. - * - * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>. - */ + //-Override- public Object evaluate(String expression, Object item, QName returnType) throws XPathExpressionException { - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); - } - if ( returnType == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"returnType"} ); - throw new NullPointerException ( fmsg ); - } - // Checking if requested returnType is supported. returnType need to - // be defined in XPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); - } + //this check is necessary before calling eval to maintain binary compatibility + requireNonNull(expression, "XPath expression"); + isSupported(returnType); try { - XObject resultObject = eval( expression, item ); - return getResultAsType( resultObject, returnType ); - } catch ( java.lang.NullPointerException npe ) { + XObject resultObject = eval(expression, item); + return getResultAsType(resultObject, returnType); + } catch (java.lang.NullPointerException npe) { // If VariableResolver returns null Or if we get // NullPointerException at this stage for some other reason // then we have to reurn XPathException - throw new XPathExpressionException ( npe ); - } catch ( javax.xml.transform.TransformerException te ) { + throw new XPathExpressionException (npe); + } catch (TransformerException te) { Throwable nestedException = te.getException(); - if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { + if (nestedException instanceof javax.xml.xpath.XPathFunctionException) { throw (javax.xml.xpath.XPathFunctionException)nestedException; } else { // For any other exceptions we need to throw - // XPathExpressionException ( as per spec ) - throw new XPathExpressionException ( te ); + // XPathExpressionException (as per spec) + throw new XPathExpressionException (te); } } } - private boolean isSupported( QName returnType ) { - if ( ( returnType.equals( XPathConstants.STRING ) ) || - ( returnType.equals( XPathConstants.NUMBER ) ) || - ( returnType.equals( XPathConstants.BOOLEAN ) ) || - ( returnType.equals( XPathConstants.NODE ) ) || - ( returnType.equals( XPathConstants.NODESET ) ) ) { - - return true; - } - return false; - } - - private Object getResultAsType( XObject resultObject, QName returnType ) - throws javax.xml.transform.TransformerException { - // XPathConstants.STRING - if ( returnType.equals( XPathConstants.STRING ) ) { - return resultObject.str(); - } - // XPathConstants.NUMBER - if ( returnType.equals( XPathConstants.NUMBER ) ) { - return new Double ( resultObject.num()); - } - // XPathConstants.BOOLEAN - if ( returnType.equals( XPathConstants.BOOLEAN ) ) { - return new Boolean( resultObject.bool()); - } - // XPathConstants.NODESET ---ORdered, UNOrdered??? - if ( returnType.equals( XPathConstants.NODESET ) ) { - return resultObject.nodelist(); - } - // XPathConstants.NODE - if ( returnType.equals( XPathConstants.NODE ) ) { - NodeIterator ni = resultObject.nodeset(); - //Return the first node, or null - return ni.nextNode(); - } - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString()}); - throw new IllegalArgumentException( fmsg ); + //-Override- + public String evaluate(String expression, Object item) + throws XPathExpressionException { + return (String)this.evaluate(expression, item, XPathConstants.STRING); } - - - /** - * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p> - * - * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of - * {@link XPathConstants#STRING}.</p> - * - * <p>See "Evaluation of XPath Expressions" of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * @param item The starting context (node or node list, for example). - * - * @return The <code>String</code> that is the result of evaluating the expression and - * converting the result to a <code>String</code>. - * - * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. - * @throws NullPointerException If <code>expression</code> is <code>null</code>. - */ - public String evaluate(String expression, Object item) - throws XPathExpressionException { - return (String)this.evaluate( expression, item, XPathConstants.STRING ); - } - - /** - * <p>Compile an XPath expression for later evaluation.</p> - * - * <p>If <code>expression</code> contains any {@link XPathFunction}s, - * they must be available via the {@link XPathFunctionResolver}. - * An {@link XPathExpressionException} will be thrown if the <code>XPathFunction</code> - * cannot be resovled with the <code>XPathFunctionResolver</code>.</p> - * - * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * - * @return Compiled XPath expression. - - * @throws XPathExpressionException If <code>expression</code> cannot be compiled. - * @throws NullPointerException If <code>expression</code> is <code>null</code>. - */ + //-Override- public XPathExpression compile(String expression) throws XPathExpressionException { - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); - } + requireNonNull(expression, "XPath expression"); try { com.sun.org.apache.xpath.internal.XPath xpath = new XPath (expression, null, - prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); + prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT); // Can have errorListener XPathExpressionImpl ximpl = new XPathExpressionImpl (xpath, prefixResolver, functionResolver, variableResolver, - featureSecureProcessing, useServiceMechanism, featureManager ); + featureSecureProcessing, useServiceMechanism, featureManager); return ximpl; - } catch ( javax.xml.transform.TransformerException te ) { - throw new XPathExpressionException ( te ) ; + } catch (TransformerException te) { + throw new XPathExpressionException (te) ; } } - - /** - * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> - * and return the result as the specified type.</p> - * - * <p>This method builds a data model for the {@link InputSource} and calls - * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * @param source The input source of the document to evaluate over. - * @param returnType The desired return type. - * - * @return The <code>Object</code> that encapsulates the result of evaluating the expression. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code> - * is <code>null</code>. - */ + //-Override- public Object evaluate(String expression, InputSource source, QName returnType) throws XPathExpressionException { - // Checking validity of different parameters - if( source== null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"source"} ); - throw new NullPointerException ( fmsg ); - } - if ( expression == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"XPath expression"} ); - throw new NullPointerException ( fmsg ); - } - if ( returnType == null ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, - new Object[] {"returnType"} ); - throw new NullPointerException ( fmsg ); - } - - //Checking if requested returnType is supported. - //returnType need to be defined in XPathConstants - if ( !isSupported ( returnType ) ) { - String fmsg = XSLMessages.createXPATHMessage( - XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, - new Object[] { returnType.toString() } ); - throw new IllegalArgumentException ( fmsg ); - } + isSupported(returnType); try { - - Document document = getParser().parse( source ); - - XObject resultObject = eval( expression, document ); - return getResultAsType( resultObject, returnType ); - } catch ( SAXException e ) { - throw new XPathExpressionException ( e ); - } catch( IOException e ) { - throw new XPathExpressionException ( e ); - } catch ( javax.xml.transform.TransformerException te ) { + Document document = getDocument(source); + XObject resultObject = eval(expression, document); + return getResultAsType(resultObject, returnType); + } catch (TransformerException te) { Throwable nestedException = te.getException(); - if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { + if (nestedException instanceof javax.xml.xpath.XPathFunctionException) { throw (javax.xml.xpath.XPathFunctionException)nestedException; } else { - throw new XPathExpressionException ( te ); + throw new XPathExpressionException (te); } } - } - - - - /** - * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> - * and return the result as a <code>String</code>.</p> - * - * <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a - * <code>returnType</code> of {@link XPathConstants#STRING}.</p> - * - * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec - * for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>expression</code> or <code>source</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * @param source The <code>InputSource</code> of the document to evaluate over. - * - * @return The <code>String</code> that is the result of evaluating the expression and - * converting the result to a <code>String</code>. - * - * @throws XPathExpressionException If expression cannot be evaluated. - * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>. - */ + //-Override- public String evaluate(String expression, InputSource source) throws XPathExpressionException { - return (String)this.evaluate( expression, source, XPathConstants.STRING ); + return (String)this.evaluate(expression, source, XPathConstants.STRING); } - /** - * <p>Reset this <code>XPath</code> to its original configuration.</p> - * - * <p><code>XPath</code> is reset to the same state as when it was created with - * {@link XPathFactory#newXPath()}. - * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s - * thus saving resources associated with the creation of new <code>XPath</code>s.</p> - * - * <p>The reset <code>XPath</code> is not guaranteed to have the same - * {@link XPathFunctionResolver}, {@link XPathVariableResolver} - * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}. - * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>, - * <code>XPathVariableResolver</code> - * and <code>NamespaceContext</code>.</p> - */ + //-Override- public void reset() { this.variableResolver = this.origVariableResolver; this.functionResolver = this.origFunctionResolver; this.namespaceContext = null; } + //-Override- + public <T> T evaluateExpression(String expression, Object item, Class<T> type) + throws XPathExpressionException { + isSupportedClassType(type); + try { + XObject resultObject = eval(expression, item); + if (type.isAssignableFrom(XPathEvaluationResult.class)) { + return getXPathResult(resultObject, type); + } else { + return XPathResultImpl.getValue(resultObject, type); + } + } catch (TransformerException te) { + throw new XPathExpressionException (te); + } + } + + //-Override- + public XPathEvaluationResult<?> evaluateExpression(String expression, Object item) + throws XPathExpressionException { + return evaluateExpression(expression, item, XPathEvaluationResult.class); + } + + //-Override- + public <T> T evaluateExpression(String expression, InputSource source, Class<T> type) + throws XPathExpressionException { + Document document = getDocument(source); + return evaluateExpression(expression, document, type); + } + + //-Override- + public XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source) + throws XPathExpressionException { + return evaluateExpression(expression, source, XPathEvaluationResult.class); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.apache.xpath.internal.jaxp; + +import com.sun.org.apache.xalan.internal.res.XSLMessages; +import com.sun.org.apache.xalan.internal.utils.FactoryImpl; +import com.sun.org.apache.xalan.internal.utils.FeatureManager; +import com.sun.org.apache.xml.internal.dtm.DTM; +import com.sun.org.apache.xpath.internal.objects.XObject; +import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; +import java.io.IOException; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathEvaluationResult; +import javax.xml.xpath.XPathExpressionException; +import javax.xml.xpath.XPathFunctionResolver; +import javax.xml.xpath.XPathNodes; +import javax.xml.xpath.XPathVariableResolver; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.traversal.NodeIterator; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * This class contains several utility methods used by XPathImpl and + * XPathExpressionImpl + */ +class XPathImplUtil { + XPathFunctionResolver functionResolver; + XPathVariableResolver variableResolver; + JAXPPrefixResolver prefixResolver; + boolean useServiceMechanism = true; + // By default Extension Functions are allowed in XPath Expressions. If + // Secure Processing Feature is set on XPathFactory then the invocation of + // extensions function need to throw XPathFunctionException + boolean featureSecureProcessing = false; + FeatureManager featureManager; + + /** + * Evaluate an XPath context using the internal XPath engine + * @param contextItem The XPath context + * @param xpath The internal XPath engine + * @return an XObject + * @throws javax.xml.transform.TransformerException If the expression cannot be evaluated. + */ + XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath) + throws javax.xml.transform.TransformerException { + com.sun.org.apache.xpath.internal.XPathContext xpathSupport; + if (functionResolver != null) { + JAXPExtensionsProvider jep = new JAXPExtensionsProvider( + functionResolver, featureSecureProcessing, featureManager); + xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(jep); + } else { + xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); + } + + xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); + XObject xobj; + + Node contextNode = (Node)contextItem; + // We always need to have a ContextNode with Xalan XPath implementation + // To allow simple expression evaluation like 1+1 we are setting + // dummy Document as Context Node + if (contextNode == null) { + xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver); + } else { + xobj = xpath.execute(xpathSupport, contextNode, prefixResolver); + } + + return xobj; + } + + /** + * Parse the input source and return a Document. + * @param source The {@code InputSource} of the document + * @return a DOM Document + * @throws XPathExpressionException if there is an error parsing the source. + */ + Document getDocument(InputSource source) + throws XPathExpressionException { + requireNonNull(source, "Source"); + try { + // we'd really like to cache those DocumentBuilders, but we can't because: + // 1. thread safety. parsers are not thread-safe, so at least + // we need one instance per a thread. + // 2. parsers are non-reentrant, so now we are looking at having a + // pool of parsers. + // 3. then the class loading issue. The look-up procedure of + // DocumentBuilderFactory.newInstance() depends on context class loader + // and system properties, which may change during the execution of JVM. + // + // so we really have to create a fresh DocumentBuilder every time we need one + // - KK + DocumentBuilderFactory dbf = FactoryImpl.getDOMFactory(useServiceMechanism); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + return dbf.newDocumentBuilder().parse(source); + } catch (ParserConfigurationException | SAXException | IOException e) { + throw new XPathExpressionException (e); + } + } + + /** + * Get result depending on the QName type defined in XPathConstants + * @param resultObject the result of an evaluation + * @param returnType the return type + * @return result per the return type + * @throws TransformerException if the result can not be converted to + * the specified return type. + */ + Object getResultAsType(XObject resultObject, QName returnType) + throws TransformerException { + // XPathConstants.STRING + if (returnType.equals(XPathConstants.STRING)) { + return resultObject.str(); + } + // XPathConstants.NUMBER + if (returnType.equals(XPathConstants.NUMBER)) { + return resultObject.num(); + } + // XPathConstants.BOOLEAN + if (returnType.equals(XPathConstants.BOOLEAN)) { + return resultObject.bool(); + } + // XPathConstants.NODESET ---ORdered, UNOrdered??? + if (returnType.equals(XPathConstants.NODESET)) { + return resultObject.nodelist(); + } + // XPathConstants.NODE + if (returnType.equals(XPathConstants.NODE)) { + NodeIterator ni = resultObject.nodeset(); + //Return the first node, or null + return ni.nextNode(); + } + // If isSupported check is already done then the execution path + // shouldn't come here. Being defensive + String fmsg = XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] { returnType.toString()}); + throw new IllegalArgumentException (fmsg); + } + + /** + * Construct an XPathExpressionResult object based on the result of the + * evaluation and cast to the specified class type. + * @param <T> The class type + * @param resultObject the result of an evaluation + * @param type The class type expected to be returned by the XPath expression. + * @return an instance of the specified type or null if the XObject returned + * an UNKNOWN object type. + * @throws TransformerException if there is an error converting the result + * to the specified type. It's unlikely to happen. This is mostly needed + * by the internal XPath engine. + */ + <T> T getXPathResult(XObject resultObject, Class<T> type) + throws TransformerException { + int resultType = resultObject.getType(); + + switch (resultType) { + case XObject.CLASS_BOOLEAN : + return type.cast(new XPathResultImpl<>(resultObject, Boolean.class)); + case XObject.CLASS_NUMBER : + return type.cast(new XPathResultImpl<>(resultObject, Double.class)); + case XObject.CLASS_STRING : + return type.cast(new XPathResultImpl<>(resultObject, String.class)); + case XObject.CLASS_NODESET : + return type.cast(new XPathResultImpl<>(resultObject, XPathNodes.class)); + case XObject.CLASS_RTREEFRAG : //NODE + return type.cast(new XPathResultImpl<>(resultObject, Node.class)); + } + + return null; + } + + /** + * Check whether or not the specified type is supported + * @param <T> The class type + * @param type The type to be checked + * @throws IllegalArgumentException if the type is not supported + */ + <T> void isSupportedClassType(Class<T> type) { + requireNonNull(type, "The class type"); + if (type.isAssignableFrom(Boolean.class) || + type.isAssignableFrom(Double.class) || + type.isAssignableFrom(Integer.class) || + type.isAssignableFrom(Long.class) || + type.isAssignableFrom(String.class) || + type.isAssignableFrom(XPathNodes.class) || + type.isAssignableFrom(Node.class) || + type.isAssignableFrom(XPathEvaluationResult.class)) { + return; + } + String fmsg = XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] { type.toString() }); + throw new IllegalArgumentException (fmsg); + } + + /** + * Check if the requested returnType is supported. + * @param returnType the return type + * @throws IllegalArgumentException if the return type is not supported + */ + void isSupported(QName returnType) { + requireNonNull(returnType, "returnType"); + if (returnType.equals(XPathConstants.STRING) || + returnType.equals(XPathConstants.NUMBER) || + returnType.equals(XPathConstants.BOOLEAN) || + returnType.equals(XPathConstants.NODE) || + returnType.equals(XPathConstants.NODESET)) { + return; + } + String fmsg = XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, + new Object[] { returnType.toString() }); + throw new IllegalArgumentException (fmsg); + } + + /** + * Checks that the specified parameter is not {@code null}. + * + * @param <T> the type of the reference + * @param param the parameter to check for nullity + * @param paramName the parameter name + * @throws NullPointerException if {@code param} is {@code null} + */ + <T> void requireNonNull(T param, String paramName) { + if (param == null) { + String fmsg = XSLMessages.createXPATHMessage( + XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, + new Object[] {paramName}); + throw new NullPointerException (fmsg); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathNodesImpl.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.apache.xpath.internal.jaxp; + +import java.util.Iterator; +import javax.xml.xpath.XPathException; +import javax.xml.xpath.XPathNodes; +import javax.xml.xpath.XPathEvaluationResult.XPathResultType; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * This class implements XPathNodes that represents a set of nodes selected by + * evaluating an expression. + */ +public class XPathNodesImpl implements XPathNodes { + Class<Node> elementType; + NodeList nodeList = null; + + public XPathNodesImpl(NodeList nodeList, Class<Node> elementType) { + this.nodeList = nodeList; + this.elementType = elementType; + } + + @Override + public Iterator<Node> iterator() { + return new NodeSetIterator<>(elementType); + } + + class NodeSetIterator<E> implements Iterator<E> { + int currentIndex; + Class<E> elementType; + NodeSetIterator(Class<E> elementType) { + this.elementType = elementType; + } + public boolean hasNext() { + if (nodeList != null) { + return currentIndex < nodeList.getLength(); + } + + return false; + } + + public E next() { + if (nodeList != null && nodeList.getLength() > 0) { + return elementType.cast(nodeList.item(currentIndex++)); + } + return null; + } + } + + @Override + public int size() { + if (nodeList != null) { + return nodeList.getLength(); + } + return 0; + } + + @Override + public Node get(int index) throws XPathException { + if (index <0 || index >= size()) { + throw new IndexOutOfBoundsException("Index " + index + " is out of bounds"); + } + if (nodeList != null) { + return nodeList.item(index); + } + return null; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathResultImpl.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.org.apache.xpath.internal.jaxp; + +import com.sun.org.apache.xpath.internal.objects.XObject; +import java.util.Objects; +import javax.xml.transform.TransformerException; +import javax.xml.xpath.XPathNodes; +import javax.xml.xpath.XPathEvaluationResult; +import javax.xml.xpath.XPathEvaluationResult.XPathResultType; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.traversal.NodeIterator; + + +/** + * This is the implementation of XPathEvaluationResult that represents the + * result of the evaluation of an XPath expression within the context of a + * particular node. + */ +class XPathResultImpl<T> implements XPathEvaluationResult<T> { + + XObject resultObject; + int resultType; + Class<T> type; + XPathResultType mapToType; + NodeList nodeList = null; + int currentIndex; + Node currentNode; + + boolean boolValue = false; + Node node = null; + double numValue; + String strValue; + + /** + * Construct an XPathEvaluationResult object. + * + * @param resultObject internal XPath result object + * @param type class type + * @throws TransformerException if there is an error reading the XPath + * result. + */ + public XPathResultImpl(XObject resultObject, Class<T> type) + throws TransformerException { + this.resultObject = resultObject; + resultType = resultObject.getType(); + this.type = type; + getResult(resultObject); + } + + /** + * Return the result type as an enum specified by {@code XPathResultType} + * @return the result type + */ + @Override + public XPathResultType type() { + return mapToType; + } + + /** + * Returns the value of the result as the type <T> specified for the class. + * + * @return The value of the result. + */ + @Override + public T value() { + Objects.requireNonNull(type); + try { + return getValue(resultObject, type); + } catch (TransformerException ex) { + throw new RuntimeException(ex); + } + } + + /** + * Read the XObject and set values in accordance with the result type + * @param resultObject internal XPath result object + * @throws TransformerException if there is an error reading the XPath + * result. + */ + private void getResult(XObject resultObject) throws TransformerException { + switch (resultType) { + case XObject.CLASS_BOOLEAN: + boolValue = resultObject.bool(); + mapToType = XPathResultType.BOOLEAN; + break; + case XObject.CLASS_NUMBER: + numValue = resultObject.num(); + mapToType = XPathResultType.NUMBER; + break; + case XObject.CLASS_STRING: + strValue = resultObject.str(); + mapToType = XPathResultType.STRING; + break; + case XObject.CLASS_NODESET: + mapToType = XPathResultType.NODESET; + nodeList = resultObject.nodelist(); + break; + case XObject.CLASS_RTREEFRAG: //NODE + mapToType = XPathResultType.NODE; + NodeIterator ni = resultObject.nodeset(); + //Return the first node, or null + node = ni.nextNode(); + break; + } + } + + /** + * Read the internal result object and return the value in accordance with + * the type specified. + * + * @param <T> The expected class type. + * @param resultObject internal XPath result object + * @param type the class type + * @return The value of the result, null in case of unexpected type. + * @throws TransformerException if there is an error reading the XPath + * result. + */ + static <T> T getValue(XObject resultObject, Class<T> type) throws TransformerException { + Objects.requireNonNull(type); + if (type.isAssignableFrom(XPathEvaluationResult.class)) { + return type.cast(new XPathResultImpl<T>(resultObject, type)); + } + int resultType = classToInternalType(type); + switch (resultType) { + case XObject.CLASS_BOOLEAN: + return type.cast(resultObject.bool()); + case XObject.CLASS_NUMBER: + if (Double.class.isAssignableFrom(type)) { + return type.cast(resultObject.num()); + } else if (Integer.class.isAssignableFrom(type)) { + return type.cast((int)resultObject.num()); + } else if (Long.class.isAssignableFrom(type)) { + return type.cast((long)resultObject.num()); + } + /* + This is to suppress warnings. By the current specification, + among numeric types, only Double, Integer and Long are supported. + */ + break; + case XObject.CLASS_STRING: + return type.cast(resultObject.str()); + case XObject.CLASS_NODESET: + XPathNodes nodeSet = new XPathNodesImpl(resultObject.nodelist(), + Node.class); + return type.cast(nodeSet); + case XObject.CLASS_RTREEFRAG: //NODE + NodeIterator ni = resultObject.nodeset(); + //Return the first node, or null + return type.cast(ni.nextNode()); + } + + return null; + } + + /** + * Map the specified class type to the internal result type + * + * @param <T> The expected class type. + * @param type the class type + * @return the internal XObject type. + */ + static <T> int classToInternalType(Class<T> type) { + if (type.isAssignableFrom(Boolean.class)) { + return XObject.CLASS_BOOLEAN; + } else if (Number.class.isAssignableFrom(type)) { + return XObject.CLASS_NUMBER; + } else if (type.isAssignableFrom(String.class)) { + return XObject.CLASS_STRING; + } else if (type.isAssignableFrom(XPathNodes.class)) { + return XObject.CLASS_NODESET; + } else if (type.isAssignableFrom(Node.class)) { + return XObject.CLASS_RTREEFRAG; + } + return XObject.CLASS_NULL; + } +}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPath.java Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,12 @@ package javax.xml.xpath; -import org.xml.sax.InputSource; +import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; -import javax.xml.namespace.NamespaceContext; +import org.xml.sax.InputSource; /** - * <p><code>XPath</code> provides access to the XPath evaluation environment and expressions.</p> + * {@code XPath} provides access to the XPath evaluation environment and expressions. * * <a name="XPath-evaluation"/> * <table border="1" cellpadding="2"> @@ -39,7 +39,6 @@ * <th colspan="2">Evaluation of XPath Expressions.</th> * </tr> * </thead> - * <tbody> * <tr> * <td>context</td> * <td> @@ -55,8 +54,8 @@ * If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver} * set with {@link #setXPathVariableResolver(XPathVariableResolver resolver)}. * An {@link XPathExpressionException} is raised if the variable resolver is undefined or - * the resolver returns <code>null</code> for the variable. - * The value of a variable must be immutable through the course of any single evaluation.</p> + * the resolver returns {@code null} for the variable. + * The value of a variable must be immutable through the course of any single evaluation. * </td> * </tr> * <tr> @@ -65,7 +64,7 @@ * If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver} * set with {@link #setXPathFunctionResolver(XPathFunctionResolver resolver)}. * An {@link XPathExpressionException} is raised if the function resolver is undefined or - * the function resolver returns <code>null</code> for the function.</p> + * the function resolver returns {@code null} for the function. * </td> * </tr> * <tr> @@ -80,7 +79,7 @@ * <td> * This result of evaluating an expression is converted to an instance of the desired return type. * Valid return types are defined in {@link XPathConstants}. - * Conversion to the return type follows XPath conversion rules.</p> + * Conversion to the return type follows XPath conversion rules. * </td> * </tr> * </table> @@ -88,9 +87,9 @@ * <p>An XPath object is not thread-safe and not reentrant. * In other words, it is the application's responsibility to make * sure that one {@link XPath} object is not used from - * more than one thread at any given time, and while the <code>evaluate</code> + * more than one thread at any given time, and while the {@code evaluate} * method is invoked, applications may not recursively call - * the <code>evaluate</code> method. + * the {@code evaluate} method. * <p> * * @author <a href="Norman.Walsh@Sun.com">Norman Walsh</a> @@ -100,191 +99,189 @@ */ public interface XPath { - /** - * <p>Reset this <code>XPath</code> to its original configuration.</p> - * - * <p><code>XPath</code> is reset to the same state as when it was created with - * {@link XPathFactory#newXPath()}. - * <code>reset()</code> is designed to allow the reuse of existing <code>XPath</code>s - * thus saving resources associated with the creation of new <code>XPath</code>s.</p> - * - * <p>The reset <code>XPath</code> is not guaranteed to have the same {@link XPathFunctionResolver}, {@link XPathVariableResolver} - * or {@link NamespaceContext} <code>Object</code>s, e.g. {@link Object#equals(Object obj)}. - * It is guaranteed to have a functionally equal <code>XPathFunctionResolver</code>, <code>XPathVariableResolver</code> - * and <code>NamespaceContext</code>.</p> - */ - public void reset(); /** - * <p>Establish a variable resolver.</p> + * Reset this {@code XPath} to its original configuration. + * + * <p>{@code XPath} is reset to the same state as when it was created with + * {@link XPathFactory#newXPath()}. + * {@code reset()} is designed to allow the reuse of existing {@code XPath}s + * thus saving resources associated with the creation of new {@code XPath}s. * - * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p> + * <p>The reset {@code XPath} is not guaranteed to have the same + * {@link XPathFunctionResolver}, {@link XPathVariableResolver} + * or {@link NamespaceContext} {@code Object}s, e.g. {@link Object#equals(Object obj)}. + * It is guaranteed to have a functionally equal {@code XPathFunctionResolver}, + * {@code XPathVariableResolver} and {@code NamespaceContext}. + */ + public void reset(); + + /** + * Establish a variable resolver. + * + * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}. * * @param resolver Variable resolver. * - * @throws NullPointerException If <code>resolver</code> is <code>null</code>. + * @throws NullPointerException If {@code resolver} is {@code null}. */ public void setXPathVariableResolver(XPathVariableResolver resolver); /** - * <p>Return the current variable resolver.</p> + * Return the current variable resolver. * - * <p><code>null</code> is returned in no variable resolver is in effect.</p> + * <p>{@code null} is returned in no variable resolver is in effect. * * @return Current variable resolver. */ public XPathVariableResolver getXPathVariableResolver(); /** - * <p>Establish a function resolver.</p> + * Establish a function resolver. * - * <p>A <code>NullPointerException</code> is thrown if <code>resolver</code> is <code>null</code>.</p> + * <p>A {@code NullPointerException} is thrown if {@code resolver} is {@code null}. * * @param resolver XPath function resolver. * - * @throws NullPointerException If <code>resolver</code> is <code>null</code>. + * @throws NullPointerException If {@code resolver} is {@code null}. */ public void setXPathFunctionResolver(XPathFunctionResolver resolver); /** - * <p>Return the current function resolver.</p> - * - * <p><code>null</code> is returned in no function resolver is in effect.</p> + * Return the current function resolver. + * <p> + * {@code null} is returned in no function resolver is in effect. * * @return Current function resolver. */ public XPathFunctionResolver getXPathFunctionResolver(); /** - * <p>Establish a namespace context.</p> + * Establish a namespace context. * - * <p>A <code>NullPointerException</code> is thrown if <code>nsContext</code> is <code>null</code>.</p> + * <p>A {@code NullPointerException} is thrown if {@code nsContext} is {@code null}. * * @param nsContext Namespace context to use. * - * @throws NullPointerException If <code>nsContext</code> is <code>null</code>. + * @throws NullPointerException If {@code nsContext} is {@code null}. */ public void setNamespaceContext(NamespaceContext nsContext); /** - * <p>Return the current namespace context.</p> + * Return the current namespace context. * - * <p><code>null</code> is returned in no namespace context is in effect.</p> + * <p>{@code null} is returned in no namespace context is in effect. * * @return Current Namespace context. */ public NamespaceContext getNamespaceContext(); /** - * <p>Compile an XPath expression for later evaluation.</p> + * Compile an XPath expression for later evaluation. * - * <p>If <code>expression</code> contains any {@link XPathFunction}s, + * <p>If {@code expression} contains any {@link XPathFunction}s, * they must be available via the {@link XPathFunctionResolver}. * An {@link XPathExpressionException} will be thrown if the - * <code>XPathFunction</code> - * cannot be resovled with the <code>XPathFunctionResolver</code>.</p> + * {@code XPathFunction} + * cannot be resovled with the {@code XPathFunctionResolver}. * - * <p>If <code>expression</code> contains any variables, the + * <p>If {@code expression} contains any variables, the * {@link XPathVariableResolver} in effect - * <strong>at compile time</strong> will be used to resolve them.</p> - * - * <p>If <code>expression</code> is <code>null</code>, a <code>NullPointerException</code> is thrown.</p> + * <strong>at compile time</strong> will be used to resolve them. * * @param expression The XPath expression. * * @return Compiled XPath expression. - * @throws XPathExpressionException If <code>expression</code> cannot be compiled. - * @throws NullPointerException If <code>expression</code> is <code>null</code>. + * @throws XPathExpressionException If {@code expression} cannot be compiled. + * @throws NullPointerException If {@code expression} is {@code null}. */ public XPathExpression compile(String expression) throws XPathExpressionException; /** - * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p> + * Evaluate an {@code XPath} expression in the specified context and + * return the result as the specified type. * - * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, - * variable, function and <code>QName</code> resolution and return type conversion.</p> + * <p> + * See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> + * for context item evaluation, variable, function and {@code QName} resolution + * and return type conversion. + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} ( + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. + * + * @param expression The XPath expression. + * @param item The context the XPath expression will be evaluated in. + * @param returnType The result type expected to be returned by the XPath expression. + * + * @return The result of evaluating an XPath expression as an {@code Object} of {@code returnType}. + * + * @throws XPathExpressionException If {@code expression} cannot be evaluated. + * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants} ( * {@link XPathConstants#NUMBER NUMBER}, * {@link XPathConstants#STRING STRING}, * {@link XPathConstants#BOOLEAN BOOLEAN}, * {@link XPathConstants#NODE NODE} or - * {@link XPathConstants#NODESET NODESET}) - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a - * <code>NullPointerException</code> is thrown.</p> - * - * @param expression The XPath expression. - * @param item The starting context (a node, for example). - * @param returnType The desired return type. - * - * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>. - * - * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>. + * {@link XPathConstants#NODESET NODESET}). + * @throws NullPointerException If {@code expression or returnType} is {@code null}. */ public Object evaluate(String expression, Object item, QName returnType) throws XPathExpressionException; /** - * <p>Evaluate an XPath expression in the specified context and return the result as a <code>String</code>.</p> + * Evaluate an XPath expression in the specified context and return the result as a {@code String}. * - * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a <code>returnType</code> of - * {@link XPathConstants#STRING}.</p> + * <p>This method calls {@link #evaluate(String expression, Object item, QName returnType)} with a {@code returnType} of + * {@link XPathConstants#STRING}. * * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> + * variable, function and QName resolution and return type conversion. * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>expression</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. + * + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. * * @param expression The XPath expression. - * @param item The starting context (a node, for example). + * @param item The context the XPath expression will be evaluated in. * - * @return The <code>String</code> that is the result of evaluating the expression and - * converting the result to a <code>String</code>. + * @return The result of evaluating an XPath expression as a {@code String}. * - * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. - * @throws NullPointerException If <code>expression</code> is <code>null</code>. + * @throws XPathExpressionException If {@code expression} cannot be evaluated. + * @throws NullPointerException If {@code expression} is {@code null}. */ public String evaluate(String expression, Object item) throws XPathExpressionException; /** - * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> - * and return the result as the specified type.</p> + * Evaluate an XPath expression in the context of the specified {@code InputSource} + * and return the result as the specified type. * * <p>This method builds a data model for the {@link InputSource} and calls - * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object.</p> + * {@link #evaluate(String expression, Object item, QName returnType)} on the resulting document object. * * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> - * - * <p>If <code>expression</code>, <code>source</code> or <code>returnType</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> + * variable, function and QName resolution and return type conversion. * * @param expression The XPath expression. * @param source The input source of the document to evaluate over. * @param returnType The desired return type. * - * @return The <code>Object</code> that encapsulates the result of evaluating the expression. + * @return The {@code Object} that encapsulates the result of evaluating the expression. * * @throws XPathExpressionException If expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>expression</code>, <code>source</code> or <code>returnType</code> - * is <code>null</code>. + * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}. + * @throws NullPointerException If {@code expression, source or returnType} is {@code null}. */ public Object evaluate( String expression, @@ -293,27 +290,209 @@ throws XPathExpressionException; /** - * <p>Evaluate an XPath expression in the context of the specified <code>InputSource</code> - * and return the result as a <code>String</code>.</p> + * Evaluate an XPath expression in the context of the specified {@code InputSource} + * and return the result as a {@code String}. * * <p>This method calls {@link #evaluate(String expression, InputSource source, QName returnType)} with a - * <code>returnType</code> of {@link XPathConstants#STRING}.</p> + * {@code returnType} of {@link XPathConstants#STRING}. * * <p>See <a href="#XPath-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, - * variable, function and QName resolution and return type conversion.</p> - * - * <p>If <code>expression</code> or <code>source</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> + * variable, function and QName resolution and return type conversion. * * @param expression The XPath expression. - * @param source The <code>InputSource</code> of the document to evaluate over. + * @param source The {@code InputSource} of the document to evaluate over. * - * @return The <code>String</code> that is the result of evaluating the expression and - * converting the result to a <code>String</code>. + * @return The {@code String} that is the result of evaluating the expression and + * converting the result to a {@code String}. * * @throws XPathExpressionException If expression cannot be evaluated. - * @throws NullPointerException If <code>expression</code> or <code>source</code> is <code>null</code>. + * @throws NullPointerException If {@code expression or source} is {@code null}. */ public String evaluate(String expression, InputSource source) throws XPathExpressionException; + + /** + * Evaluate an XPath expression in the specified context and return + * the result with the type specified through the {@code class type} + * + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. + * + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * (T)evaluate(expression, item, + * XPathEvaluationResult.XPathResultType.getQNameType(type)); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying + * XPathEvaluationResult as the type will result in IllegalArgumentException. + * Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override + * this method. + * + * @param <T> The class type that will be returned by the XPath expression. + * @param expression The XPath expression. + * @param item The context the XPath expression will be evaluated in. + * @param type The class type expected to be returned by the XPath expression. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If {@code type} is not of the types + * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType}, + * or XPathEvaluationResult is specified as the type but an implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available. + * @throws NullPointerException If {@code expression or type} is {@code null}. + * + * @since 1.9 + */ + default <T>T evaluateExpression(String expression, Object item, Class<T> type) + throws XPathExpressionException { + return type.cast(evaluate(expression, item, + XPathEvaluationResult.XPathResultType.getQNameType(type))); + } + + /** + * Evaluate an XPath expression in the specified context. This is equivalent to + * calling {@link #evaluateExpression(String expression, Object item, Class type)} + * with type {@link XPathEvaluationResult}: + * <pre> {@code + * evaluateExpression(expression, item, XPathEvaluationResult.class); + * }</pre> + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. + * + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * evaluateExpression(expression, item, XPathEvaluationResult.class); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} + * type, the default implementation of this method will always throw an + * IllegalArgumentException. Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore + * override this method. + * + * @param expression The XPath expression. + * @param item The context the XPath expression will be evaluated in. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If the implementation of this method + * does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type. + * @throws NullPointerException If {@code expression} is {@code null}. + * + * @since 1.9 + */ + default XPathEvaluationResult<?> evaluateExpression(String expression, Object item) + throws XPathExpressionException + { + return evaluateExpression(expression, item, XPathEvaluationResult.class); + } + + /** + * Evaluate an XPath expression in the context of the specified {@code source} + * and return the result as specified. + * <p> + * This method builds a data model for the {@link InputSource} and calls + * {@link #evaluateExpression(String expression, Object item, Class type)} + * on the resulting document object. The data model is usually + * {@link org.w3c.dom.Document} + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + (T)evaluate(expression, source, + XPathEvaluationResult.XPathResultType.getQNameType(type)); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying + * XPathEvaluationResult as the type will result in IllegalArgumentException. + * Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override + * this method. + * + * @param <T> The class type that will be returned by the XPath expression. + * @param expression The XPath expression. + * @param source The input source of the document to evaluate over. + * @param type The class type expected to be returned by the XPath expression. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If {@code type} is not of the types + * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType + * XPathResultType}, or XPathEvaluationResult is specified as the type but an + * implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available. + * @throws NullPointerException If {@code expression, source or type}is {@code null}. + * + * @since 1.9 + */ + default <T>T evaluateExpression(String expression, InputSource source, Class<T> type) + throws XPathExpressionException + { + return type.cast(evaluate(expression, source, + XPathEvaluationResult.XPathResultType.getQNameType(type))); + } + + /** + * Evaluate an XPath expression in the specified context. This is equivalent to + * calling {@link #evaluateExpression(String expression, Object item, Class type)} + * with type {@link XPathEvaluationResult}: + * <pre> {@code + * evaluateExpression(expression, item, XPathEvaluationResult.class); + * }</pre> + * <p> + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * evaluateExpression(expression, source, XPathEvaluationResult.class); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} + * type, the default implementation of this method will always throw an + * IllegalArgumentException. Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore + * override this method. + * + * @param expression The XPath expression. + * @param source The input source of the document to evaluate over. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If the implementation of this method + * does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type. + * @throws NullPointerException If {@code expression or source} is {@code null}. + * + * @since 1.9 + */ + default XPathEvaluationResult<?> evaluateExpression(String expression, InputSource source) + throws XPathExpressionException + { + return evaluateExpression(expression, source, XPathEvaluationResult.class); + } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathEvaluationResult.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.xpath; + +import java.util.Objects; +import javax.xml.namespace.QName; +import org.w3c.dom.Node; +/** + * The {@code XPathEvaluationResult} interface represents the result of the + * evaluation of an XPath expression within the context of a particular node. + * The evaluation of an XPath expression can result in various result types as + * defined in XML Path Language (XPath) Version 1.0. + * <p> + * + * @param <T> the object type returned by the XPath evaluation. + * @see <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version + * 1.0</a> + * + * @since 1.9 + */ +public interface XPathEvaluationResult<T> { + + /** + * XPathResultType represents possible return types of an XPath evaluation. + * Provided as an enum type, it allows the use of switch statement. At the + * same time, a mapping is provided between the original QName types in + * {@link XPathConstants} and class types used in the generic methods. + */ + public static enum XPathResultType { + /** + * Any type that represents any of the 5 other types listed below. + * Maps to {@link XPathEvaluationResult}. + */ + ANY(new QName("http://www.w3.org/1999/XSL/Transform", "any"), XPathEvaluationResult.class), + /** + * The XPath 1.0 boolean data type. Maps to Java {@link Boolean}. + */ + BOOLEAN(XPathConstants.BOOLEAN, Boolean.class), + /** + * The XPath 1.0 Number data type. Maps to Java {@link Number}. Of the + * subtypes of Number, only Double, Integer and Long are required. + */ + NUMBER(XPathConstants.NUMBER, Number.class), + /** + * The XPath 1.0 String data type. Maps to Java {@link String}. + */ + STRING(XPathConstants.STRING, String.class), + /** + * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.NodeList}. + */ + NODESET(XPathConstants.NODESET, XPathNodes.class), + /** + * The XPath 1.0 NodeSet data type. Maps to {@link org.w3c.dom.Node}. + */ + NODE(XPathConstants.NODE, Node.class); + + final QName qnameType; + final Class<?> clsType; + XPathResultType(QName qnameType, Class<?> clsType) { + this.qnameType = qnameType; + this.clsType = clsType; + } + + /** + * Compares this type to the specified class type. + * @param clsType class type + * @return true if the argument is not null and is a class type that + * matches that this type represents, false otherwise. + */ + private boolean equalsClassType(Class<?> clsType) { + Objects.nonNull(clsType); + if (clsType.isAssignableFrom(this.clsType)) { + return true; + } + return false; + } + + /** + * Returns the QName type as specified in {@link XPathConstants} that + * corresponds to the specified class type. + * @param clsType a class type that the enum type supports + * @return the QName type that matches with the specified class type, + * null if there is no match + */ + static public QName getQNameType(Class<?> clsType) { + for (XPathResultType type : XPathResultType.values()) { + if (type.equalsClassType(clsType)) { + return type.qnameType; + } + } + return null; + } + } + + /** + * Return the result type as an enum specified by {@code XPathResultType} + * @return the result type + */ + public XPathResultType type(); + + /** + * Returns the value of the result as the type <T> specified for the class. + * + * @return The value of the result. + */ + public T value(); + +}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathExpression.java Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ package javax.xml.xpath; +import javax.xml.namespace.QName; import org.xml.sax.InputSource; -import javax.xml.namespace.QName; /** - * <p><code>XPathExpression</code> provides access to compiled XPath expressions.</p> + * <p>{@code XPathExpression} provides access to compiled XPath expressions.</p> * * <a name="XPathExpression-evaluation"/> * <table border="1" cellpadding="2"> @@ -53,7 +53,7 @@ * <td> * If the expression contains a variable reference, its value will be found through the {@link XPathVariableResolver}. * An {@link XPathExpressionException} is raised if the variable resolver is undefined or - * the resolver returns <code>null</code> for the variable. + * the resolver returns {@code null} for the variable. * The value of a variable must be immutable through the course of any single evaluation.</p> * </td> * </tr> @@ -62,7 +62,7 @@ * <td> * If the expression contains a function reference, the function will be found through the {@link XPathFunctionResolver}. * An {@link XPathExpressionException} is raised if the function resolver is undefined or - * the function resolver returns <code>null</code> for the function.</p> + * the function resolver returns {@code null} for the function.</p> * </td> * </tr> * <tr> @@ -84,9 +84,9 @@ * <p>An XPath expression is not thread-safe and not reentrant. * In other words, it is the application's responsibility to make * sure that one {@link XPathExpression} object is not used from - * more than one thread at any given time, and while the <code>evaluate</code> + * more than one thread at any given time, and while the {@code evaluate} * method is invoked, applications may not recursively call - * the <code>evaluate</code> method. + * the {@code evaluate} method. * <p> * * @author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a> @@ -96,50 +96,56 @@ */ public interface XPathExpression { + /** * <p>Evaluate the compiled XPath expression in the specified context and return the result as the specified type.</p> * * <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, * variable, function and QName resolution and return type conversion.</p> * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. - * If <code>returnType</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. * - * @param item The starting context (a node, for example). - * @param returnType The desired return type. + * @param item The context the XPath expression will be evaluated in. + * @param returnType The result type expected to be returned by the XPath expression. * - * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to - * <code>returnType</code>. + * @return The {@code Object} that is the result of evaluating the expression and converting the result to + * {@code returnType}. * * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>returnType</code> is <code>null</code>. + * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}. + * @throws NullPointerException If {@code returnType} is {@code null}. */ public Object evaluate(Object item, QName returnType) throws XPathExpressionException; /** - * <p>Evaluate the compiled XPath expression in the specified context and return the result as a <code>String</code>.</p> + * <p>Evaluate the compiled XPath expression in the specified context and return the result as a {@code String}.</p> * - * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a <code>returnType</code> of + * <p>This method calls {@link #evaluate(Object item, QName returnType)} with a {@code returnType} of * {@link XPathConstants#STRING}.</p> * * <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, * variable, function and QName resolution and return type conversion.</p> * - * <p>If a <code>null</code> value is provided for - * <code>item</code>, an empty document will be used for the - * context. + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. * - * @param item The starting context (a node, for example). + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. * - * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a - * <code>String</code>. + * @param item The context the XPath expression will be evaluated in. + * + * @return The result of evaluating an XPath expression as a {@code String}. * * @throws XPathExpressionException If the expression cannot be evaluated. */ @@ -147,7 +153,7 @@ throws XPathExpressionException; /** - * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as the + * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as the * specified type.</p> * * <p>This method builds a data model for the {@link InputSource} and calls @@ -156,45 +162,225 @@ * <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, * variable, function and QName resolution and return type conversion.</p> * - * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants}, - * then an <code>IllegalArgumentException</code> is thrown.</p> + * <p>If {@code returnType} is not one of the types defined in {@link XPathConstants}, + * then an {@code IllegalArgumentException} is thrown.</p> * - * <p>If <code>source</code> or <code>returnType</code> is <code>null</code>, - * then a <code>NullPointerException</code> is thrown.</p> + * <p>If {@code source} or {@code returnType} is {@code null}, + * then a {@code NullPointerException} is thrown.</p> * - * @param source The <code>InputSource</code> of the document to evaluate over. + * @param source The {@code InputSource} of the document to evaluate over. * @param returnType The desired return type. * - * @return The <code>Object</code> that is the result of evaluating the expression and converting the result to - * <code>returnType</code>. + * @return The {@code Object} that is the result of evaluating the expression and converting the result to + * {@code returnType}. * * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. - * @throws NullPointerException If <code>source</code> or <code>returnType</code> is <code>null</code>. + * @throws IllegalArgumentException If {@code returnType} is not one of the types defined in {@link XPathConstants}. + * @throws NullPointerException If {@code source or returnType} is {@code null}. */ public Object evaluate(InputSource source, QName returnType) throws XPathExpressionException; /** - * <p>Evaluate the compiled XPath expression in the context of the specified <code>InputSource</code> and return the result as a - * <code>String</code>.</p> + * <p>Evaluate the compiled XPath expression in the context of the specified {@code InputSource} and return the result as a + * {@code String}.</p> * - * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a <code>returnType</code> of + * <p>This method calls {@link #evaluate(InputSource source, QName returnType)} with a {@code returnType} of * {@link XPathConstants#STRING}.</p> * * <p>See <a href="#XPathExpression-evaluation">Evaluation of XPath Expressions</a> for context item evaluation, * variable, function and QName resolution and return type conversion.</p> * - * <p>If <code>source</code> is <code>null</code>, then a <code>NullPointerException</code> is thrown.</p> + * <p>If {@code source} is {@code null}, then a {@code NullPointerException} is thrown.</p> * - * @param source The <code>InputSource</code> of the document to evaluate over. + * @param source The {@code InputSource} of the document to evaluate over. * - * @return The <code>String</code> that is the result of evaluating the expression and converting the result to a - * <code>String</code>. + * @return The {@code String} that is the result of evaluating the expression and converting the result to a + * {@code String}. * * @throws XPathExpressionException If the expression cannot be evaluated. - * @throws NullPointerException If <code>source</code> is <code>null</code>. + * @throws NullPointerException If {@code source} is {@code null}. */ public String evaluate(InputSource source) throws XPathExpressionException; + + /** + * Evaluate the compiled XPath expression in the specified context, and return + * the result with the type specified through the {@code class type}. + * + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. + * + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * (T)evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type)); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying + * XPathEvaluationResult as the type will result in IllegalArgumentException. + * Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override + * this method. + * + * @param <T> The class type that will be returned by the XPath expression. + * @param item The context the XPath expression will be evaluated in. + * @param type The class type expected to be returned by the XPath expression. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If {@code type} is not of the types + * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType + * XPathResultType}, or XPathEvaluationResult is specified as the type but an + * implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type is not available. + * @throws NullPointerException If {@code type} is {@code null}. + * + * @since 1.9 + */ + default <T>T evaluateExpression(Object item, Class<T> type) + throws XPathExpressionException + { + return type.cast(evaluate(item, XPathEvaluationResult.XPathResultType.getQNameType(type))); + } + + /** + * Evaluate the compiled XPath expression in the specified context. This is + * equivalent to calling {@link #evaluateExpression(Object item, Class type)} + * with type {@link XPathEvaluationResult}: + * <pre> {@code + * evaluateExpression(item, XPathEvaluationResult.class); + * }</pre> + * <p> + * The parameter {@code item} represents the context the XPath expression + * will be operated on. The type of the context is implementation-dependent. + * If the value is {@code null}, the operation must have no dependency on + * the context, otherwise an XPathExpressionException will be thrown. + * + * @implNote + * The type of the context is usually {@link org.w3c.dom.Node}. + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * evaluateExpression(item, XPathEvaluationResult.class); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} + * type, the default implementation of this method will always throw an + * IllegalArgumentException. Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore + * override this method. + * + * @param item The context the XPath expression will be evaluated in. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If the implementation of this method + * does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type. + * + * @since 1.9 + */ + default XPathEvaluationResult<?> evaluateExpression(Object item) + throws XPathExpressionException + { + return evaluateExpression(item, XPathEvaluationResult.class); + } + + /** + * Evaluate the compiled XPath expression in the specified context, + * and return the result with the type specified through the {@code class type} + * <p> + * This method builds a data model for the {@link InputSource} and calls + * {@link #evaluateExpression(Object item, Class type)} on the resulting + * document object. + * <P> + * By default, the JDK's data model is {@link org.w3c.dom.Document}. + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + (T)evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type)); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type, specifying + * XPathEvaluationResult as the type will result in IllegalArgumentException. + * Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must override + * this method. + * + * @param <T> The class type that will be returned by the XPath expression. + * @param source The {@code InputSource} of the document to evaluate over. + * @param type The class type expected to be returned by the XPath expression. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If {@code type} is not of the types + * corresponding to the types defined in the {@link XPathEvaluationResult.XPathResultType + * XPathResultType}, or XPathEvaluationResult is specified as the type but an + * implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type + * is not available. + * @throws NullPointerException If {@code source or type} is {@code null}. + * + * @since 1.9 + */ + default <T>T evaluateExpression(InputSource source, Class<T> type) + throws XPathExpressionException + { + return type.cast(evaluate(source, XPathEvaluationResult.XPathResultType.getQNameType(type))); + } + + /** + * Evaluate the compiled XPath expression in the specified context. This is + * equivalent to calling {@link #evaluateExpression(InputSource source, Class type)} + * with type {@link XPathEvaluationResult}: + * <pre> {@code + * evaluateExpression(source, XPathEvaluationResult.class); + * }</pre> + * <p> + * + * @implSpec + * The default implementation in the XPath API is equivalent to: + * <pre> {@code + * (XPathEvaluationResult)evaluateExpression(source, XPathEvaluationResult.class); + * }</pre> + * + * Since the {@code evaluate} method does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} + * type, the default implementation of this method will always throw an + * IllegalArgumentException. Any implementation supporting the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type must therefore + * override this method. + * + * @param source The {@code InputSource} of the document to evaluate over. + * + * @return The result of evaluating the expression. + * + * @throws XPathExpressionException If the expression cannot be evaluated. + * @throws IllegalArgumentException If the implementation of this method + * does not support the + * {@link XPathEvaluationResult.XPathResultType#ANY ANY} type. + * @throws NullPointerException If {@code source} is {@code null}. + * + * @since 1.9 + */ + default XPathEvaluationResult<?> evaluateExpression(InputSource source) + throws XPathExpressionException + { + return evaluateExpression(source, XPathEvaluationResult.class); + } }
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactory.java Wed Feb 04 18:22:46 2015 -0800 @@ -117,7 +117,7 @@ * and returns it if it is successfully created. * </li> * <li> - * ${java.home}/conf/jaxp.properties is read and the value associated with the key being the system property above is looked for. + * ${java.home}/lib/jaxp.properties is read and the value associated with the key being the system property above is looked for. * If present, the value is processed just like above. * </li> * <li>
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathFactoryFinder.java Wed Feb 04 18:22:46 2015 -0800 @@ -176,9 +176,9 @@ String javah = ss.getSystemProperty( "java.home" ); String configFile = javah + File.separator + - "conf" + File.separator + "jaxp.properties"; + "lib" + File.separator + "jaxp.properties"; - // try to read from $java.home/conf/jaxp.properties + // try to read from $java.home/lib/jaxp.properties try { if(firstTime){ synchronized(cacheProps){ @@ -193,7 +193,7 @@ } } final String factoryClassName = cacheProps.getProperty(propertyName); - debugPrintln("found " + factoryClassName + " in $java.home/conf/jaxp.properties"); + debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties"); if (factoryClassName != null) { xpathFactory = createInstance(factoryClassName, true);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/XPathNodes.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.xml.xpath; + +import java.util.Iterator; +import org.w3c.dom.Node; + +/** + * XPathNodes represents a set of nodes selected by a location path as specified + * in <a href="http://www.w3.org/TR/xpath/#node-sets">XML Path Language (XPath) + * Version 1.0, 3.3 Node-sets</a>. + * + * @since 1.9 + */ +public interface XPathNodes extends Iterable<Node> { + + /** + * Returns an iterator of the Nodes. + * + * @return an Iterator. + */ + @Override + public abstract Iterator<Node> iterator(); + + /** + * Returns the number of items in the result + * + * @return The number of items in the result + */ + public abstract int size(); + + /** + * Returns a Node at the specified position + * + * @param index Index of the element to return. + * @return The Node at the specified position. + * @throws javax.xml.xpath.XPathException If the index is out of range + * (index < 0 || index >= size()) + */ + public abstract Node get(int index) + throws XPathException; +}
--- a/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxp/src/java.xml/share/classes/javax/xml/xpath/package.html Wed Feb 04 18:22:46 2015 -0800 @@ -1,6 +1,8 @@ -<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<html> +<head> <!-- -Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. This code is free software; you can redistribute it and/or modify it @@ -23,35 +25,35 @@ or visit www.oracle.com if you need additional information or have any questions. --> +</head> +<body bgcolor="white"> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml"> -<head> -<title>javax.xml.xpath</title> -<meta name="@author" content="mailto:Ben@galbraiths.org" /> -<meta name="@author" content="mailto:Norman.Walsh@Sun.com" /> -<meta name="@author" content="mailto:Jeff.Suttor@Sun.com" /> -<meta name="@see" content="http://www.w3.org/TR/xpath" /> -<meta name="@since" content="1.5" /> -</head> - -<body> - -<p>This package provides an <em>object-model neutral</em> API for the +This package provides an <em>object-model neutral</em> API for the evaluation of XPath expressions and access to the evaluation environment. -</p> -<p>The following XML standards apply:</p> - -<ul> -<li><a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li> -</ul> +<p> +The XPath API supports <a href="http://www.w3.org/TR/xpath"> + XML Path Language (XPath) Version 1.0</a> <hr /> -<h2>XPath Overview</h2> +<ul> + <li><a href='#XPath.Overview'>1. XPath Overview</a></li> + <li><a href='#XPath.Expressions'>2. XPath Expressions</a></li> + <li><a href='#XPath.Datatypes'>3. XPath Data Types</a> + <ul> + <li><a href='#XPath.Datatypes.QName'>3.1 QName Types</a> + <li><a href='#XPath.Datatypes.Class'>3.2 Class Types</a> + <li><a href='#XPath.Datatypes.Enum'>3.3 Enum Types</a> + </ul> + </li> + <li><a href='#XPath.Context'>4. XPath Context</a></li> + <li><a href='#XPath.Use'>5. Using the XPath API</a></li> +</ul> +<p> +<a name="XPath.Overview"></a> +<h3>1. XPath Overview</h3> <p>The XPath language provides a simple, concise syntax for selecting nodes from an XML document. XPath also provides rules for converting a @@ -67,7 +69,8 @@ replace many lines of DOM API code. </p> -<h3>XPath Expressions</h3> +<a name="XPath.Expressions"></a> +<h3>2. XPath Expressions</h3> <p>An XPath <em>expression</em> is composed of a <em>location path</em> and one or more optional <em>predicates</em>. Expressions @@ -76,18 +79,22 @@ <p>The following is an example of a simple XPath expression:</p> +<blockquote> <pre> /foo/bar </pre> +</blockquote> <p>This example would select the <code><bar></code> element in an XML document such as the following:</p> +<blockquote> <pre> <foo> -<bar/> + <bar/> </foo> </pre> +</blockquote> <p>The expression <code>/foo/bar</code> is an example of a location path. While XPath location paths resemble Unix-style file system @@ -96,30 +103,36 @@ <code><bar></code> elements in the following document would be selected by the <code>/foo/bar</code> expression:</p> +<blockquote> <pre> <foo> -<bar/> -<bar/> -<bar/> + <bar/> + <bar/> + <bar/> </foo> </pre> +</blockquote> <p>A special location path operator, <code>//</code>, selects nodes at any depth in an XML document. The following example selects all <code><bar></code> elements regardless of their location in a document:</p> +<blockquote> <pre> //bar </pre> +</blockquote> <p>A wildcard operator, *, causes all element nodes to be selected. The following example selects all children elements of a -<code><foo></code> element:</p> +<code><foo></code> element: +<blockquote> <pre> /foo/* </pre> +</blockquote> <p>In addition to element nodes, XPath location paths may also address attribute nodes, text nodes, comment nodes, and processing instruction @@ -166,35 +179,27 @@ <code><foo></code> elements that contain an <code>include</code> attribute with the value of <code>true</code>:</p> +<blockquote> <pre> //foo[@include='true'] </pre> +</blockquote> <p>Predicates may be appended to each other to further refine an expression, such as:</p> +<blockquote> <pre> //foo[@include='true'][@mode='bar'] </pre> - -<h3>Using the XPath API</h3> - -<p> -The following example demonstrates using the XPath API to select one -or more nodes from an XML document:</p> +</blockquote> -<pre> -XPath xpath = XPathFactory.newInstance().newXPath(); -String expression = "/widgets/widget"; -InputSource inputSource = new InputSource("widgets.xml"); -NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET); -</pre> - -<h3>XPath Expressions and Types</h3> +<a name="XPath.Datatypes"></a> +<h3>3. XPath Data Types</h3> <p>While XPath expressions select nodes in the XML document, the XPath API allows the selected nodes to be coalesced into one of the -following other data types:</p> +following data types:</p> <ul> <li><code>Boolean</code></li> @@ -202,14 +207,10 @@ <li><code>String</code></li> </ul> -<p>The desired return type is specified by a {@link -javax.xml.namespace.QName} parameter in method call used to evaluate -the expression, which is either a call to -<code>XPathExpression.evalute(...)</code> or to one of the -<code>XPath.evaluate(...)</code> convenience methods. The allowed -QName values are specified as constants in the {@link -javax.xml.xpath.XPathConstants} class; they are:</p> - +<a name="XPath.Datatypes.QName"></a> +<h3>3.1 QName types</h3> +The XPath API defines the following {@link javax.xml.namespace.QName} types to +represent return types of an XPath evaluation: <ul> <li>{@link javax.xml.xpath.XPathConstants#NODESET}</li> <li>{@link javax.xml.xpath.XPathConstants#NODE}</li> @@ -218,26 +219,71 @@ <li>{@link javax.xml.xpath.XPathConstants#NUMBER}</li> </ul> +<p>The return type is specified by a {@link javax.xml.namespace.QName} parameter +in method call used to evaluate the expression, which is either a call to +<code>XPathExpression.evalute(...)</code> or <code>XPath.evaluate(...)</code> +methods. + <p>When a <code>Boolean</code> return type is requested, <code>Boolean.TRUE</code> is returned if one or more nodes were -selected; otherwise, <code>Boolean.FALSE</code> is returned.</p> +selected; otherwise, <code>Boolean.FALSE</code> is returned. <p>The <code>String</code> return type is a convenience for retrieving the character data from a text node, attribute node, comment node, or processing-instruction node. When used on an element node, the value of the child text nodes is returned. -</p> <p>The <code>Number</code> return type attempts to coalesce the text of a node to a <code>double</code> data type. -</p> + +<a name="XPath.Datatypes.Class"></a> +<h3>3.2 Class types</h3> +In addition to the QName types, the XPath API supports the use of Class types +through the <code>XPathExpression.evaluteExpression(...)</code> or +<code>XPath.evaluateExpression(...)</code> methods. -<h3>XPath Context</h3> +The XPath data types are mapped to Class types as follows: +<ul> +<li><code>Boolean</code> -- <code>Boolean.class</code></li> +<li><code>Number</code> -- <code>Number.class</code></li> +<li><code>String</code> -- <code>String.class</code></li> +<li><code>Nodeset</code> -- <code>XPathNodes.class</code></li> +<li><code>Node</code> -- <code>Node.class</code></li> +</ul> + +<p> +Of the subtypes of Number, only Double, Integer and Long are supported. + +<a name="XPath.Datatypes.Enum"></a> +<h3>3.3 Enum types</h3> +Enum types are defined in {@link javax.xml.xpath.XPathEvaluationResult.XPathResultType} +that provide mappings between the QName and Class types above. The result of +evaluating an expression using the <code>XPathExpression.evaluteExpression(...)</code> +or <code>XPath.evaluateExpression(...)</code> methods will be of one of these types. + +<a name="XPath.Context"></a> +<h3>4. XPath Context</h3> <p>XPath location paths may be relative to a particular node in the -document, known as the <code>context</code>. Consider the following -XML document:</p> +document, known as the <code>context</code>. A context consists of: +<ul> + <li>a node (the context node)</li> + <li>a pair of non-zero positive integers (the context position and the context size)</li> + <li>a set of variable bindings</li> + <li>a function library</li> + <li>the set of namespace declarations in scope for the expression</li> +</ul> +<p> +It is an XML document tree represented as a hierarchy of nodes, a +{@link org.w3c.dom.Node} for example, in the JDK implementation. + +<a name="XPath.Use"></a> +<h3>5. Using the XPath API</h3> + +Consider the following XML document: +<p> +<blockquote> <pre> <widgets> <widget> @@ -246,36 +292,88 @@ </widget> </widgets> </pre> +</blockquote> -<p>The <code><widget></code> element can be selected with the -following XPath API code:</p> +<p> +The <code><widget></code> element can be selected with the following process: +<blockquote> <pre> // parse the XML as a W3C Document DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document = builder.parse(new File("/widgets.xml")); +//Get an XPath object and evaluate the expression XPath xpath = XPathFactory.newInstance().newXPath(); String expression = "/widgets/widget"; Node widgetNode = (Node) xpath.evaluate(expression, document, XPathConstants.NODE); + +//or using the evaluateExpression method +Node widgetNode = xpath.evaluateExpression(expression, document, Node.class); </pre> +</blockquote> <p>With a reference to the <code><widget></code> element, a -relative XPath expression can now written to select the +relative XPath expression can be written to select the <code><manufacturer></code> child element:</p> +<blockquote> <pre> XPath xpath = XPathFactory.newInstance().newXPath(); <strong>String expression = "manufacturer";</strong> Node manufacturerNode = (Node) xpath.evaluate(expression, <strong>widgetNode</strong>, XPathConstants.NODE); + +//or using the evaluateExpression method +Node manufacturerNode = xpath.evaluateExpression(expression, <strong>widgetNode</strong>, Node.class); </pre> +</blockquote> + +<p> +In the above example, the XML file is read into a DOM Document before being passed +to the XPath API. The following code demonstrates the use of InputSource to +leave it to the XPath implementation to process it: + +<blockquote> +<pre> +XPath xpath = XPathFactory.newInstance().newXPath(); +String expression = "/widgets/widget"; +InputSource inputSource = new InputSource("widgets.xml"); +NodeList nodes = (NodeList) xpath.evaluate(expression, inputSource, XPathConstants.NODESET); + +//or using the evaluateExpression method +XPathNodes nodes = xpath.evaluate(expression, inputSource, XPathNodes.class); +</pre> +</blockquote> -<ul> -<li>Author <a href="mailto:Ben@galbraiths.org">Ben Galbraith</a></li> -<li>Author <a href="mailto:Norman.Walsh@Sun.com">Norman Walsh</a></li> -<li>Author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a></li> -<li>See <a href="http://www.w3.org/TR/xpath">XML Path Language (XPath) Version 1.0</a></li> -<li>Since 1.5</li> -</ul> +<p> +In the above cases, the type of the expected results are known. In case where +the result type is unknown or any type, the {@link javax.xml.xpath.XPathEvaluationResult} +may be used to determine the return type. The following code demonstrates the usage: +<blockquote> +<pre> +XPathEvaluationResult<?> result = xpath.evaluateExpression(expression, document); +switch (result.type()) { + case NODESET: + XPathNodes nodes = (XPathNodes)result.value(); + ... + break; +} +</pre> +</blockquote> + +<p> +The XPath 1.0 Number data type is defined as a double. However, the XPath +specification also provides functions that returns Integer type. To facilitate +such operations, the XPath API allows Integer and Long to be used in +{@code evaluateExpression} method such as the following code: +<p> +<blockquote> +<pre> +int count = xpath.evaluate("count(/widgets/widget)", document, Integer.class); +</pre> +</blockquote> + +@since 1.5 + </body> </html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/SchemaFactoryTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/TypeInfoProviderTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation.ptests; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR; +import static jaxp.library.JAXPTestUtilities.filenameToURL; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import java.io.File; +import java.io.IOException; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.TypeInfoProvider; +import javax.xml.validation.ValidatorHandler; + +import jaxp.library.JAXPFileBaseTest; + +import org.testng.annotations.Test; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +/* + * @summary test ValidatorHandler.getTypeInfoProvider() + */ +public class TypeInfoProviderTest extends JAXPFileBaseTest { + + private ValidatorHandler validatorHandler; + + @Test + public void test() throws SAXException, ParserConfigurationException, IOException { + + SchemaFactory sf = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI); + Schema schema = sf.newSchema(new File(XML_DIR + "shiporder11.xsd")); + validatorHandler = schema.newValidatorHandler(); + MyDefaultHandler myDefaultHandler = new MyDefaultHandler(); + validatorHandler.setContentHandler(myDefaultHandler); + + InputSource is = new InputSource(filenameToURL(XML_DIR + "shiporder11.xml")); + + SAXParserFactory parserFactory = SAXParserFactory.newInstance(); + parserFactory.setNamespaceAware(true); + XMLReader xmlReader = parserFactory.newSAXParser().getXMLReader(); + xmlReader.setContentHandler(validatorHandler); + xmlReader.parse(is); + + } + + private class MyDefaultHandler extends DefaultHandler { + + public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { + TypeInfoProvider typeInfoProvider = validatorHandler.getTypeInfoProvider(); + int index = atts.getIndex("orderid"); + if (index != -1) { + System.out.println(" Index " + index); + System.out.println(" ElementType " + typeInfoProvider.getElementTypeInfo().getTypeName()); + assertEquals(typeInfoProvider.getAttributeTypeInfo(index).getTypeName(), "string"); + assertTrue(typeInfoProvider.isSpecified(index)); + assertFalse(typeInfoProvider.isIdAttribute(index)); + } + + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorHandlerTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation.ptests; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; + +import java.io.File; + +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.ValidatorHandler; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.xml.sax.ContentHandler; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.DefaultHandler; + +/* + * @summary Class containing the test cases for ValidatorHandler API + */ +public class ValidatorHandlerTest { + @BeforeClass + public void setup() throws SAXException { + schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI).newSchema(new File(XML_DIR + "test.xsd")); + + assertNotNull(schema); + } + + @Test + public void testErrorHandler() { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNull(validatorHandler.getErrorHandler(), "When ValidatorHandler is created, initially ErrorHandler should not be set."); + + ErrorHandler handler = new MyErrorHandler(); + validatorHandler.setErrorHandler(handler); + assertSame(validatorHandler.getErrorHandler(), handler); + + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testGetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + validatorHandler.getProperty(FEATURE_NAME); + + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testSetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + validatorHandler.setProperty(FEATURE_NAME, "test"); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testGetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNotNull(validatorHandler); + validatorHandler.getProperty(null); + + } + + @Test(expectedExceptions = NullPointerException.class) + public void testSetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNotNull(validatorHandler); + validatorHandler.setProperty(null, "test"); + } + + public void testFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertFalse(validatorHandler.getFeature(FEATURE_NAME), "The feature should be false by default."); + + validatorHandler.setFeature(FEATURE_NAME, true); + assertTrue(validatorHandler.getFeature(FEATURE_NAME), "The feature should be false by default."); + + } + + @Test(expectedExceptions = NullPointerException.class) + public void testGetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNotNull(validatorHandler); + validatorHandler.getFeature(null); + + } + + @Test(expectedExceptions = NullPointerException.class) + public void testSetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNotNull(validatorHandler); + validatorHandler.setFeature(null, true); + } + + @Test + public void testContentHandler() { + ValidatorHandler validatorHandler = getValidatorHandler(); + assertNull(validatorHandler.getContentHandler(), "When ValidatorHandler is created, initially ContentHandler should not be set."); + + ContentHandler handler = new DefaultHandler(); + validatorHandler.setContentHandler(handler); + assertSame(validatorHandler.getContentHandler(), handler); + + validatorHandler.setContentHandler(null); + assertNull(validatorHandler.getContentHandler()); + + } + + private ValidatorHandler getValidatorHandler() { + return schema.newValidatorHandler(); + } + + private static final String FEATURE_NAME = "http://xml.org/sax/features/namespace-prefixes"; + + private Schema schema; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/ptests/ValidatorTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,207 @@ +/* + * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation.ptests; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI; +import static javax.xml.validation.ptests.ValidationTestConst.XML_DIR; +import static jaxp.library.JAXPTestUtilities.filenameToURL; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertSame; + +import java.io.File; +import java.io.IOException; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.sax.SAXResult; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import jaxp.library.JAXPFileBaseTest; + +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import org.xml.sax.helpers.DefaultHandler; + +/* + * @summary Class containing the test cases for Validator API + */ +public class ValidatorTest extends JAXPFileBaseTest { + + @BeforeClass + public void setup() throws SAXException, IOException, ParserConfigurationException { + schema = SchemaFactory.newInstance(W3C_XML_SCHEMA_NS_URI).newSchema(new File(XML_DIR + "test.xsd")); + + assertNotNull(schema); + + xmlFileUri = filenameToURL(XML_DIR + "test.xml"); + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + xmlDoc = dbf.newDocumentBuilder().parse(xmlFileUri); + } + + @Test + public void testValidateStreamSource() throws SAXException, IOException { + Validator validator = getValidator(); + validator.setErrorHandler(new MyErrorHandler()); + validator.validate(getStreamSource()); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testValidateNullSource() throws SAXException, IOException { + Validator validator = getValidator(); + assertNotNull(validator); + validator.validate(null); + } + + @Test + public void testErrorHandler() { + Validator validator = getValidator(); + assertNull(validator.getErrorHandler(), "When Validator is created, initially ErrorHandler should not be set."); + + ErrorHandler mh = new MyErrorHandler(); + validator.setErrorHandler(mh); + assertSame(validator.getErrorHandler(), mh); + + } + + @DataProvider(name = "source-result") + public Object[][] getSourceAndResult() { + return new Object[][] { + { getStreamSource(), null }, + { getSAXSource(), getSAXResult() }, + { getDOMSource(), getDOMResult() }, + { getSAXSource(), null }, + { getDOMSource(), null } }; + } + + @Test(dataProvider = "source-result") + public void testValidateWithResult(Source source, Result result) throws SAXException, IOException { + Validator validator = getValidator(); + validator.validate(source, result); + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testGetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + validator.getProperty(UNRECOGNIZED_NAME); + + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testSetUnrecognizedProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + validator.setProperty(UNRECOGNIZED_NAME, "test"); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testGetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + assertNotNull(validator); + validator.getProperty(null); + + } + + @Test(expectedExceptions = NullPointerException.class) + public void testSetNullProperty() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + assertNotNull(validator); + validator.setProperty(null, "test"); + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testGetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + validator.getFeature(UNRECOGNIZED_NAME); + + } + + @Test(expectedExceptions = SAXNotRecognizedException.class) + public void testSetUnrecognizedFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + validator.setFeature(UNRECOGNIZED_NAME, true); + } + + @Test(expectedExceptions = NullPointerException.class) + public void testGetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + assertNotNull(validator); + validator.getFeature(null); + + } + + @Test(expectedExceptions = NullPointerException.class) + public void testSetNullFeature() throws SAXNotRecognizedException, SAXNotSupportedException { + Validator validator = getValidator(); + assertNotNull(validator); + validator.setFeature(null, true); + } + + private Validator getValidator() { + return schema.newValidator(); + } + + private Source getStreamSource() { + return new StreamSource(xmlFileUri); + } + + private Source getSAXSource() { + return new SAXSource(new InputSource(xmlFileUri)); + } + + private Result getSAXResult() { + SAXResult saxResult = new SAXResult(); + saxResult.setHandler(new DefaultHandler()); + return saxResult; + } + + private Source getDOMSource() { + return new DOMSource(xmlDoc); + } + + private Result getDOMResult() { + return new DOMResult(); + } + + private static final String UNRECOGNIZED_NAME = "http://xml.org/sax/features/namespace-prefixes"; + private String xmlFileUri; + private Schema schema; + private Document xmlDoc; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<shiporder orderid="889923" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:noNamespaceSchemaLocation="shiporder.xsd"> +<orderperson>John Smith</orderperson> +<shipto> +<name>Ola Nordmann</name> +<address>Langgt 23</address> +<city>4000 Stavanger</city> +<country>Norway</country> +</shipto> +<item> +<title>Empire Burlesque</title> +<note>Special Edition</note> +<quantity>1</quantity> +<price>10.90</price> +</item> +<item> +<title>Hide your heart</title> +<quantity>1</quantity> +<price>9.90</price> +</item> +</shiporder> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder11.xsd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + +<!-- definition of simple elements --> +<xs:element name="orderperson" type="xs:string"/> +<xs:element name="name" type="xs:string"/> +<xs:element name="address" type="xs:string"/> +<xs:element name="city" type="xs:string"/> +<xs:element name="country" type="xs:string"/> +<xs:element name="title" type="xs:string"/> +<xs:element name="note" type="xs:string"/> +<xs:element name="quantity" type="xs:positiveInteger"/> +<xs:element name="price" type="xs:decimal"/> + +<!-- definition of attributes --> +<xs:attribute name="orderid" type="xs:string"/> + +<!-- definition of complex elements --> +<xs:element name="shipto"> +<xs:complexType> +<xs:sequence> +<xs:element ref="name"/> +<xs:element ref="address"/> +<xs:element ref="city"/> +<xs:element ref="country"/> +</xs:sequence> +</xs:complexType> +</xs:element> +<xs:element name="item"> +<xs:complexType> +<xs:sequence> +<xs:element ref="title"/> +<xs:element ref="note" minOccurs="0"/> +<xs:element ref="quantity"/> +<xs:element ref="price"/> +</xs:sequence> +</xs:complexType> +</xs:element> + +<xs:element name="shiporder"> +<xs:complexType> +<xs:sequence> +<xs:element ref="orderperson"/> +<xs:element ref="shipto"/> +<xs:element ref="item" maxOccurs="unbounded"/> +</xs:sequence> +<xs:attribute ref="orderid" use="required"/> +</xs:complexType> +</xs:element> + +</xs:schema> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<shiporder orderid="889923" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +xsi:noNamespaceSchemaLocation="shiporder.xsd"> +<orderperson>John Smith</orderperson> +<shipto> +<name>Ola Nordmann</name> +<address>Langgt 23</address> +<city>4000 Stavanger</city> +<country>Norway</country> +</shipto> +<item> +<title>Empire Burlesque</title> +<note>Special Edition</note> +<quantity>1</quantity> +<price>10.90</price> +</item> +<item> +<title>Hide your heart</title> +<quantity>1</quantity> +<price>9.90</price> +</item> +</shiporder> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/shiporder12.xsd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + +<!-- definition of simple elements --> +<xs:element name="orderperson" type="xs:string"/> +<xs:element name="name" type="xs:string"/> +<xs:element name="address" type="xs:string"/> +<xs:element name="city" type="xs:string"/> +<xs:element name="country" type="xs:string"/> +<xs:element name="title" type="xs:string"/> +<xs:element name="note" type="xs:string"/> +<xs:element name="quantity" type="xs:positiveInteger"/> +<xs:element name="price" type="xs:decimal"/> + +<!-- definition of attributes --> +<xs:attribute name="orderid" type="xs:string"/> + +<!-- definition of complex elements --> +<xs:element name="shipto"> +<xs:complexType> +<xs:sequence> +<xs:element ref="name"/> +<xs:element ref="address"/> +<xs:element ref="city"/> +<xs:element ref="country"/> +</xs:sequence> +</xs:complexType> +</xs:element> +<xs:element name="item"> +<xs:complexType> +<xs:sequence> +<xs:element ref="title"/> +<xs:element ref="note" minOccurs="0"/> +<xs:element ref="quantity"/> +<xs:element ref="price"/> +</xs:sequence> +</xs:complexType> +</xs:element> + +<xs:element name="shiporder"> +<xs:complexType> +<xs:sequence> +<xs:element ref="orderperson"/> +<xs:element ref="shipto"/> +<xs:element ref="item" maxOccurs="unbounded"/> +</xs:sequence> +<xs:attribute ref="orderid" use="required"/> +</xs:complexType> +</xs:element> + +</xs:schema> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8" ?> + <contact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="test.xsd"> +<name> John </name> +<phone>444-121-3434</phone> +</contact>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test.xsd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" ?> + <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> +<xs:element name="contact"> +<xs:complexType> +<xs:sequence> + <xs:element name="name" type="xs:string"/> + <xs:element name="phone" type="xs:string"/> +</xs:sequence> +</xs:complexType> +</xs:element> +</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/validation/xmlfiles/test1.xsd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" ?> + <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> +<xs:element name="address"> +<xs:complexType> +<xs:sequence> + <xs:element name="street" type="xs:string"/> + <xs:element name="city" type="xs:string"/> +</xs:sequence> +</xs:complexType> +</xs:element> +</xs:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4511326.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test.gaptest; + +import java.io.StringReader; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamSource; + +import jaxp.library.JAXPBaseTest; + +import org.testng.annotations.Test; + +/* + * @bug 4511326 + * @summary In forwards-compatible mode the attribute isn't ignored + */ + +public class Bug4511326 extends JAXPBaseTest { + + private static final String XSL = "<xsl:stylesheet version='2.0' " + + "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>" + + "<xsl:template a='1' match='/'>" + + "<H2><xsl:value-of select='//author'/></H2>" + + "<H1><xsl:value-of select='//title'/></H1>" + + "</xsl:template>" + + "</xsl:stylesheet>"; + + + @Test + public void ignoreAttTest() throws TransformerConfigurationException { + /* Create a TransformFactory instance */ + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + + /* Create and init a StreamSource instance */ + StreamSource source = new StreamSource(new StringReader(XSL)); + + transformerFactory.newTransformer(source); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4512806.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test.gaptest; + +import static javax.xml.transform.OutputKeys.ENCODING; +import static javax.xml.transform.OutputKeys.INDENT; +import static org.testng.Assert.assertEquals; + +import java.io.StringReader; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamSource; + +import jaxp.library.JAXPBaseTest; + +import org.testng.annotations.Test; + +/* + * @bug 4512806 + * @summary test transformer.setOutputProperties(null) + */ +public class Bug4512806 extends JAXPBaseTest { + + @Test + public void testProperty() throws TransformerConfigurationException { + /* Create a transform factory instance */ + TransformerFactory tfactory = TransformerFactory.newInstance(); + + /* Create a StreamSource instance */ + StreamSource streamSource = new StreamSource(new StringReader(xslData)); + + transformer = tfactory.newTransformer(streamSource); + transformer.setOutputProperty(INDENT, "no"); + transformer.setOutputProperty(ENCODING, "UTF-16"); + + assertEquals(printPropertyValue(INDENT), "indent=no"); + assertEquals(printPropertyValue(ENCODING), "encoding=UTF-16"); + + transformer.setOutputProperties(null); + + assertEquals(printPropertyValue(INDENT), "indent=yes"); + assertEquals(printPropertyValue(ENCODING), "encoding=UTF-8"); + + } + + private String printPropertyValue(String name) { + return name + "=" + transformer.getOutputProperty(name); + } + + private Transformer transformer; + + private static final String xslData = "<?xml version='1.0'?>" + + "<xsl:stylesheet" + + " version='1.0'" + + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" + + ">\n" + + " <xsl:output method='xml' indent='yes'" + + " encoding='UTF-8'/>\n" + + " <xsl:template match='/'>\n" + + " Hello World! \n" + + " </xsl:template>\n" + + "</xsl:stylesheet>"; + + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515047.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test.gaptest; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import jaxp.library.JAXPBaseTest; + +import org.testng.annotations.Test; + +/* + * @bug 4515047 + * @summary test transform an empty dom source + */ + +public class Bug4515047 extends JAXPBaseTest { + + @Test + public void testCreateTxDoc() throws TransformerException, ParserConfigurationException { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + + StreamResult result = new StreamResult(System.out); + DOMSource source = new DOMSource(); + + /* This should not throw an Illegal Argument Exception */ + //Test empty DOMSource + transformer.transform(source, result); + + //Test DOMSource having only an empty node + source.setNode(DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument()); + transformer.transform(source, result); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4515660.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test.gaptest; + +import static org.testng.Assert.assertTrue; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.sax.SAXSource; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.stream.StreamResult; + +import jaxp.library.JAXPBaseTest; + +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.XMLFilterImpl; + +/* + * @bug 4515660 + * @summary verify property org.xml.sax.driver is used by SAXTransformerFactory + */ +@Test(singleThreaded = true) +public class Bug4515660 extends JAXPBaseTest { + + @BeforeClass + public void setSaxDrier() { + setSystemProperty("org.xml.sax.driver", ReaderStub.class.getName()); + } + + @AfterClass + public void clearSaxDrier() { + setSystemProperty("org.xml.sax.driver", null); + } + + @Test + public void testTransformer() throws TransformerException { + String xml = "<?xml version='1.0'?><root/>"; + ReaderStub.used = false; + + TransformerFactory transFactory = TransformerFactory.newInstance(); + Transformer transformer = transFactory.newTransformer(); + InputSource in = new InputSource(new StringReader(xml)); + SAXSource source = new SAXSource(in); + StreamResult result = new StreamResult(new StringWriter()); + + transformer.transform(source, result); + + assertTrue(ReaderStub.used); + + } + + @Test + public void testSAXTransformerFactory() throws TransformerConfigurationException { + final String xsl = "<?xml version='1.0'?>\n" + "<xsl:stylesheet" + " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'" + " version='1.0'>\n" + + " <xsl:template match='/'>Hello World!</xsl:template>\n" + "</xsl:stylesheet>\n"; + + ReaderStub.used = false; + + TransformerFactory transFactory = TransformerFactory.newInstance(); + assertTrue(transFactory.getFeature(SAXTransformerFactory.FEATURE)); + + InputSource in = new InputSource(new StringReader(xsl)); + SAXSource source = new SAXSource(in); + + transFactory.newTransformer(source); + assertTrue(ReaderStub.used); + + } + + public static class ReaderStub extends XMLFilterImpl { + static boolean used = false; + + public ReaderStub() throws ParserConfigurationException, SAXException { + super(); + super.setParent(SAXParserFactory.newInstance().newSAXParser().getXMLReader()); + used = true; + } + + public void parse(InputSource input) throws SAXException, IOException { + used = true; + super.parse(input); + } + + public void parse(String systemId) throws SAXException, IOException { + used = true; + super.parse(systemId); + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4693341.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package test.gaptest; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static jaxp.library.JAXPTestUtilities.USER_DIR; +import static jaxp.library.JAXPTestUtilities.compareDocumentWithGold; +import static org.testng.Assert.assertTrue; +import static test.gaptest.GapTestConst.GOLDEN_DIR; +import static test.gaptest.GapTestConst.XML_DIR; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import jaxp.library.JAXPFileBaseTest; + +import org.testng.annotations.Test; +import org.xml.sax.SAXException; + +/* + * @bug 4693341 + * @summary test transforming to stream with external dtd + */ + +public class Bug4693341 extends JAXPFileBaseTest { + + @Test + public void test() throws TransformerException, ParserConfigurationException, SAXException, IOException { + + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + + String out = USER_DIR + File.separator + "Bug4693341.out"; + StreamResult result = new StreamResult(new File(out)); + + String in = XML_DIR + "Bug4693341.xml"; + String golden = GOLDEN_DIR + "Bug4693341.xml"; + File file = new File(in); + StreamSource source = new StreamSource(file); + System.out.println(source.getSystemId()); + + Files.copy(Paths.get(XML_DIR + "Bug4693341.dtd"), + Paths.get(USER_DIR + File.separator + "Bug4693341.dtd"), REPLACE_EXISTING); + + transformer.transform(source, result); + + assertTrue(compareDocumentWithGold(golden, out)); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4848653.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.gaptest; + +import static jaxp.library.JAXPTestUtilities.filenameToURL; +import static test.gaptest.GapTestConst.XML_DIR; + +import java.io.IOException; + +import javax.xml.XMLConstants; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import jaxp.library.JAXPFileBaseTest; + +import org.testng.annotations.Test; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; + +/* + * @bug 4848653 + * @summary Verify JAXP schemaLanguage property is ignored if setValidating(false) + */ + +public class Bug4848653 extends JAXPFileBaseTest { + + @Test + public void test() throws IOException, SAXException, ParserConfigurationException { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + SAXParser parser = factory.newSAXParser(); + parser.setProperty("http://java.sun.com/xml/jaxp/properties/schemaLanguage", XMLConstants.W3C_XML_SCHEMA_NS_URI); + + String filename = XML_DIR + "Bug4848653.xml"; + InputSource is = new InputSource(filenameToURL(filename)); + XMLReader xmlReader = parser.getXMLReader(); + xmlReader.setErrorHandler(new MyErrorHandler()); + xmlReader.parse(is); + } + + class MyErrorHandler implements ErrorHandler { + public void error(SAXParseException exception) throws SAXParseException { + throw exception; + } + + public void warning(SAXParseException exception) throws SAXParseException { + throw exception; + } + + public void fatalError(SAXParseException exception) throws SAXParseException { + throw exception; + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/Bug4858685.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.gaptest; + +import static jaxp.library.JAXPTestUtilities.filenameToURL; +import static org.testng.Assert.assertEquals; +import static test.gaptest.GapTestConst.GOLDEN_DIR; +import static test.gaptest.GapTestConst.XML_DIR; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import jaxp.library.JAXPFileBaseTest; + +import org.testng.annotations.Test; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/* + * @bug 4858685 4894410 + * @summary test transforming text node + */ + +public class Bug4858685 extends JAXPFileBaseTest { + @Test + public void test() throws TransformerException, IOException { + String uri = XML_DIR + "certificate.xml"; + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + + Transformer transformer = transformerFactory.newTransformer(); + + // use URI as a StreamSource + StreamSource streamSource = new StreamSource(filenameToURL(uri)); + + DOMResult domResult = new DOMResult(); + + // StreamSource -> DOMResult + transformer.transform(streamSource, domResult); + + // dump DOM in a human readable form + String gotString = DOMDump.dumpDom(domResult.getNode()); + + String goldenString = new String(Files.readAllBytes(Paths.get(GOLDEN_DIR + "Bug4858685.txt"))); + + assertEquals(gotString, goldenString); + + } + + /** + * DOMDump: dump a DOM to a String in human readable form. method dumpDOM() + * is static for easy calling: + */ + private static class DOMDump { + + /** + * the maximum level to indent with blanks + */ + private static final int BLANKS_LEN = 64; + + /** + * each level of the tree will be indented with blanks for readability + */ + private static final String BLANKS = " "; + + /** + * dumpDOM will dump the DOM into a String for human readability + * + * @param domNode + * the DOM Node to dump + * @return human readabile DOM as a String + */ + public static String dumpDom(Node domNode) { + return dumpInternal(domNode, 0); + } + + /** + * dumpInternal is used internaly to recursively dump DOM Nodes + * + * @param domNode + * to dump + * @param indent + * level + * @return domNode as human readable String + */ + private static String dumpInternal(Node domNode, int indent) { + + String result = ""; + + // indent for readability + result += indentBlanks(indent); + indent += 2; + + // protect against null + if (domNode == null) { + result = result + "[null]" + "\n"; + return result; + } + + // what to output depends on NodeType + short type = domNode.getNodeType(); + switch (type) { + case Node.ATTRIBUTE_NODE: { + result += "[attribute] " + domNode.getNodeName() + "=\"" + domNode.getNodeValue() + "\""; + break; + } + case Node.CDATA_SECTION_NODE: { + result += "[cdata] " + domNode.getNodeValue(); + break; + } + case Node.COMMENT_NODE: { + result += "[comment] " + domNode.getNodeValue(); + break; + } + case Node.DOCUMENT_FRAGMENT_NODE: { + result += "[document fragment]"; + break; + } + case Node.DOCUMENT_NODE: { + result += "[document]"; + break; + } + case Node.DOCUMENT_TYPE_NODE: { + result += "[document type] " + domNode.getNodeName(); + break; + } + case Node.ELEMENT_NODE: { + result += "[element] " + domNode.getNodeName(); + // output all attributes for Element + if (domNode.hasAttributes()) { + NamedNodeMap attributes = domNode.getAttributes(); + for (int onAttribute = 0; onAttribute < attributes.getLength(); onAttribute++) { + + // seprate each attribute with a space + result += " "; + + Node attribute = attributes.item(onAttribute); + String namespaceURI = attribute.getNamespaceURI(); + String prefix = attribute.getPrefix(); + String localName = attribute.getLocalName(); + String name = attribute.getNodeName(); + String value = attribute.getNodeValue(); + + // using Namespaces? + if (namespaceURI != null) { + result += "{" + namespaceURI + "}"; + } + if (prefix != null) { + result += prefix + ":"; + } + + // name="value" + result += attribute.getNodeName() + "=\"" + attribute.getNodeValue() + "\""; + } + } + + break; + } + case Node.ENTITY_NODE: { + result += "[entity] " + domNode.getNodeName(); + break; + } + case Node.ENTITY_REFERENCE_NODE: { + result += "[entity reference] " + domNode.getNodeName(); + break; + } + case Node.NOTATION_NODE: { + result += "[notation] " + domNode.getNodeName(); + break; + } + case Node.PROCESSING_INSTRUCTION_NODE: { + result += "[pi] target=\"" + domNode.getNodeName() + "\" content=\"" + domNode.getNodeValue() + "\""; + break; + } + case Node.TEXT_NODE: { + result += "[text] " + domNode.getNodeValue(); + break; + } + default: { + result += "[unknown]"; + break; + } + } + + // humans read in lines + result += "\n"; + + // process children + NodeList children = domNode.getChildNodes(); + for (int onChild = 0; onChild < children.getLength(); onChild++) { + Node child = children.item(onChild); + result += dumpInternal(child, indent); + } + + // return human readable DOM as String + return result; + } + + /** + * indentBlanks will return a String of indent blanks + * + * @param indent + * level + * @return String of blanks + */ + private static String indentBlanks(int indent) { + if (indent == 0) { + return ""; + } + + if (indent > BLANKS_LEN) { + return BLANKS; + } + + return BLANKS.substring(0, indent + 1); + } + + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.dtd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,39 @@ +<!ELEMENT SupplierOrder (OrderId, OrderDate, ShippingAddress, LineItems)> + +<!ELEMENT OrderId (#PCDATA)> + +<!ELEMENT OrderDate (#PCDATA)> + +<!ELEMENT ShippingAddress (FirstName, LastName, Street, City, State, Country, ZipCode, Email, Phone)> + +<!ELEMENT FirstName (#PCDATA)> + +<!ELEMENT LastName (#PCDATA)> + +<!ELEMENT Street (#PCDATA)> + +<!ELEMENT City (#PCDATA)> + +<!ELEMENT State (#PCDATA)> + +<!ELEMENT Country (#PCDATA)> + +<!ELEMENT ZipCode (#PCDATA)> + +<!ELEMENT Email (#PCDATA)> + +<!ELEMENT Phone (#PCDATA)> + +<!ELEMENT LineItems (LineItem+)> + +<!ELEMENT LineItem EMPTY> + +<!ATTLIST LineItem + categoryId CDATA #REQUIRED + productId CDATA #REQUIRED + itemId CDATA #REQUIRED + lineNo CDATA #REQUIRED + quantity CDATA #REQUIRED + unitPrice CDATA #REQUIRED +> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4693341.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE SupplierOrder SYSTEM "Bug4693341.dtd" > +<SupplierOrder> +<OrderId>10016</OrderId> +<OrderDate>Wed May 29 12:45:00 PDT 2002</OrderDate> +<ShippingAddress> +<FirstName>ABC</FirstName> +<LastName>XYZ</LastName> +<Street>1234 Anywhere Street</Street> +<City>Palo Alto</City> +<State>California</State> +<Country>USA</Country> +<ZipCode>94303</ZipCode> +<Email>NULL</Email> +<Phone>NULL</Phone> +</ShippingAddress> +<LineItems> +<LineItem categoryId="BIRDS" itemId="EST-18" lineNo="0" productId="AV-CB-01" quantity="1" unitPrice="193.5"/> +</LineItems> +</SupplierOrder>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/Bug4848653.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,1 @@ +<a/>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/certificate.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<env:Envelope xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" + xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" + xmlns:ns0="http://headertest.org/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <env:Body> + <ds:X509Certificate xmlns="" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> +MIIDVjCCAxICBD6kKrMwCwYHKoZIzjgEAwUAMIGPMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex +FDASBgNVBAcTC1NhbnRhIENsYXJhMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMR4w +HAYDVQQLExVKYXZhIGFuZCBYTUwgU29mdHdhcmUxHDAaBgNVBAMTE0pXUy1TZWN1cml0eSBDbGll +bnQwHhcNMDMwNDIxMTczMDI3WhcNMDMwNzIwMTczMDI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV +BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEfMB0GA1UEChMWU3VuIE1pY3Jvc3lzdGVtcywg +SW5jLjEeMBwGA1UECxMVSmF2YSBhbmQgWE1MIFNvZnR3YXJlMRwwGgYDVQQDExNKV1MtU2VjdXJp +dHkgQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E +AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up +1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj +C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZ +T+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7 +zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAV3R+bUfh+u0yaPBV75umKvFB +ucv37ETDak889b7k72kZdGoHz3oDmp69tiNDg5r7IvKtjHGbZ6C3Nv0ycNR7Sed1QPOF4nn/tgUl +j+BvtVW3iiIRgBJ82KP+28QtwPkkxSp7n5HG0v7bE29E/juLduuhKBQTaaCvajuCFxiBrmAwCwYH +KoZIzjgEAwUAAzEAMC4CFQCCuDNmMKjgY6MV1SmAcCdnhuT6VwIVAJBOiPDnDWp2WlKAERF6nOAf +vKz9 + </ds:X509Certificate> + </env:Body> +</env:Envelope>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.dtd Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,39 @@ +<!ELEMENT SupplierOrder (OrderId, OrderDate, ShippingAddress, LineItems)> + +<!ELEMENT OrderId (#PCDATA)> + +<!ELEMENT OrderDate (#PCDATA)> + +<!ELEMENT ShippingAddress (FirstName, LastName, Street, City, State, Country, ZipCode, Email, Phone)> + +<!ELEMENT FirstName (#PCDATA)> + +<!ELEMENT LastName (#PCDATA)> + +<!ELEMENT Street (#PCDATA)> + +<!ELEMENT City (#PCDATA)> + +<!ELEMENT State (#PCDATA)> + +<!ELEMENT Country (#PCDATA)> + +<!ELEMENT ZipCode (#PCDATA)> + +<!ELEMENT Email (#PCDATA)> + +<!ELEMENT Phone (#PCDATA)> + +<!ELEMENT LineItems (LineItem+)> + +<!ELEMENT LineItem EMPTY> + +<!ATTLIST LineItem + categoryId CDATA #REQUIRED + productId CDATA #REQUIRED + itemId CDATA #REQUIRED + lineNo CDATA #REQUIRED + quantity CDATA #REQUIRED + unitPrice CDATA #REQUIRED +> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4693341.xml Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE SupplierOrder SYSTEM "Bug4693341.dtd" > +<SupplierOrder> +<OrderId>10016</OrderId> +<OrderDate>Wed May 29 12:45:00 PDT 2002</OrderDate> +<ShippingAddress> +<FirstName>ABC</FirstName> +<LastName>XYZ</LastName> +<Street>1234 Anywhere Street</Street> +<City>Palo Alto</City> +<State>California</State> +<Country>USA</Country> +<ZipCode>94303</ZipCode> +<Email>NULL</Email> +<Phone>NULL</Phone> +</ShippingAddress> +<LineItems> +<LineItem categoryId="BIRDS" itemId="EST-18" lineNo="0" productId="AV-CB-01" quantity="1" unitPrice="193.5"/> +</LineItems> +</SupplierOrder>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/functional/test/gaptest/xmlfiles/out/Bug4858685.txt Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,30 @@ +[document] + [element] env:Envelope {http://www.w3.org/2000/xmlns/}xmlns:xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:ns0="http://headertest.org/" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:xsd="http://www.w3.org/2001/XMLSchema" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + [text] + + [element] env:Body + [text] + + [element] ds:X509Certificate xmlns="" {http://www.w3.org/2000/xmlns/}xmlns:xmlns:ds="http://www.w3.org/2000/09/xmldsig#" + [text] +MIIDVjCCAxICBD6kKrMwCwYHKoZIzjgEAwUAMIGPMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0Ex +FDASBgNVBAcTC1NhbnRhIENsYXJhMR8wHQYDVQQKExZTdW4gTWljcm9zeXN0ZW1zLCBJbmMuMR4w +HAYDVQQLExVKYXZhIGFuZCBYTUwgU29mdHdhcmUxHDAaBgNVBAMTE0pXUy1TZWN1cml0eSBDbGll +bnQwHhcNMDMwNDIxMTczMDI3WhcNMDMwNzIwMTczMDI3WjCBjzELMAkGA1UEBhMCVVMxCzAJBgNV +BAgTAkNBMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEfMB0GA1UEChMWU3VuIE1pY3Jvc3lzdGVtcywg +SW5jLjEeMBwGA1UECxMVSmF2YSBhbmQgWE1MIFNvZnR3YXJlMRwwGgYDVQQDExNKV1MtU2VjdXJp +dHkgQ2xpZW50MIIBtzCCASwGByqGSM44BAEwggEfAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E +AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up +1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAhUAl2BQjxUj +C8yykrmCouuEC/BYHPUCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZ +T+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7 +zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoDgYQAAoGAV3R+bUfh+u0yaPBV75umKvFB +ucv37ETDak889b7k72kZdGoHz3oDmp69tiNDg5r7IvKtjHGbZ6C3Nv0ycNR7Sed1QPOF4nn/tgUl +j+BvtVW3iiIRgBJ82KP+28QtwPkkxSp7n5HG0v7bE29E/juLduuhKBQTaaCvajuCFxiBrmAwCwYH +KoZIzjgEAwUAAzEAMC4CFQCCuDNmMKjgY6MV1SmAcCdnhuT6VwIVAJBOiPDnDWp2WlKAERF6nOAf +vKz9 + + [text] + + [text] +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/MyErrorHandler.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation.ptests; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXParseException; + +class MyErrorHandler implements ErrorHandler { + public void error(SAXParseException exception) throws SAXParseException { + throw exception; + } + + public void warning(SAXParseException exception) throws SAXParseException { + throw exception; + } + + public void fatalError(SAXParseException exception) throws SAXParseException { + throw exception; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/libs/javax/xml/validation/ptests/ValidationTestConst.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.validation.ptests; + +import static jaxp.library.JAXPTestUtilities.FILE_SEP; +import static jaxp.library.JAXPTestUtilities.getPathByClassName; + +/** + * This class defines the path constant + */ +public class ValidationTestConst { + /** + * XML source file directory. + */ + public static final String XML_DIR = getPathByClassName(ValidationTestConst.class, + ".." + FILE_SEP + "xmlfiles"); + + /** + * Golden validation files directory. + */ + public static final String GOLDEN_DIR = getPathByClassName(ValidationTestConst.class, + ".." + FILE_SEP + "xmlfiles" + FILE_SEP + "out"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/libs/test/gaptest/GapTestConst.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test.gaptest; + +import static jaxp.library.JAXPTestUtilities.FILE_SEP; +import static jaxp.library.JAXPTestUtilities.getPathByClassName; + +/** + * This class defines the path constant + */ +public class GapTestConst { + /** + * XML source file directory. + */ + public static final String XML_DIR = getPathByClassName(GapTestConst.class, "xmlfiles"); + + /** + * Golden validation files directory. + */ + public static final String GOLDEN_DIR = getPathByClassName(GapTestConst.class, "xmlfiles" + FILE_SEP + "out"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathAnyTypeTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.xpath; + +import java.io.File; +import javax.xml.xpath.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/* + * @bug 8054196 + * @summary Test for the project XPath: support any type. This test covers the new + * evaluateExpression methods of XPath, as well as XPathNodes and XPathEvaluationResult. + */ +public class XPathAnyTypeTest extends XPathTestBase { + /* + Test for resolveFunction(QName functionName,int arity); evaluate throws + NPE if functionName is null. + */ + + @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class) + public void testCheckXPathFunctionResolver02(XPath xpath) throws XPathExpressionException { + xpath.setXPathFunctionResolver((functionName, arity) -> null); + assertEquals(xpath.evaluate(null, "5"), "2"); + } + /* + Check that NPE is thrown when expression is null. + */ + + @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class) + public void test01(XPath xpath) throws XPathExpressionException { + double result = xpath.evaluateExpression(null, (Object) null, Double.class); + } + + /* + Check that NPE is thrown when the class type is null. + */ + @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class) + public void test02(XPath xpath) throws XPathExpressionException { + double result = xpath.evaluateExpression("1+1", (Object) null, null); + } + + /* + Parameter item can be null when the expression does not depends on the + context. + */ + @Test(dataProvider = "xpath") + public void test03(XPath xpath) throws XPathExpressionException { + int result = xpath.evaluateExpression("1+1", (Object) null, Integer.class); + assertTrue(result == 2); + } + + /* + * Test return type: boolean. + */ + @Test(dataProvider = "document") + public void test04(XPath xpath, Document doc) throws XPathExpressionException { + boolean result1 = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc, Boolean.class); + assertTrue(result1); + } + + /* + * Test return type: numeric. Subtypes supported: Double, Integer and Long + */ + @Test(dataProvider = "document") + public void test05(XPath xpath, Document doc) throws XPathExpressionException { + double result1 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Double.class); + assertTrue(result1 == 3.0); + int result2 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Integer.class); + assertTrue(result2 == 3); + long result3 = xpath.evaluateExpression("count(/Customers/Customer)", doc, Long.class); + assertTrue(result3 == 3); + } + + /* + * Test return type: numeric. Of the subtypes of Number, only Double, + * Integer and Long are required. + */ + @Test(dataProvider = "invalidNumericTypes", expectedExceptions = IllegalArgumentException.class) + public void test06(XPath xpath, Class<Number> type) throws XPathExpressionException { + xpath.evaluateExpression("1+1", (Object) null, type); + } + + /* + * Test return type: String. + */ + @Test(dataProvider = "document") + public void test07(XPath xpath, Document doc) throws XPathExpressionException { + String result1 = xpath.evaluateExpression("string(/Customers/Customer[@id=3]/Phone/text())", doc, String.class); + assertTrue(result1.equals("3333333333")); + } + + /* + * Test return type: NodeSet. + */ + @Test(dataProvider = "document") + public void test08(XPath xpath, Document doc) throws XPathExpressionException { + XPathNodes nodes = xpath.evaluateExpression("/Customers/Customer", doc, XPathNodes.class); + assertTrue(nodes.size() == 3); + for (Node n : nodes) { + assertEquals(n.getLocalName(), "Customer"); + } + } + + /* + * Test return type: Node. + */ + @Test(dataProvider = "document") + public void test09(XPath xpath, Document doc) throws XPathExpressionException { + Node n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, Node.class); + assertEquals(n.getLocalName(), "Customer"); + } + + /* + * Test return type: Unsupported type. + */ + @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class) + public void test10(XPath xpath, Document doc) throws XPathExpressionException { + File n = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc, File.class); + } + + /* + * Test return type: Any::Boolean. + */ + @Test(dataProvider = "document") + public void test11(XPath xpath, Document doc) throws XPathExpressionException { + XPathEvaluationResult<?> result = xpath.evaluateExpression("boolean(/Customers/Customer[@id=3])", doc); + verifyResult(result, true); + } + + /* + * Test return type: Any::Number. + */ + @Test(dataProvider = "document") + public void test12(XPath xpath, Document doc) throws XPathExpressionException { + XPathEvaluationResult<?> result = xpath.evaluateExpression("count(/Customers/Customer)", doc); + verifyResult(result, 3.0); + } + + /* + * Test return type: Any::String. + */ + @Test(dataProvider = "document") + public void test13(XPath xpath, Document doc) throws XPathExpressionException { + XPathEvaluationResult<?> result = xpath.evaluateExpression( + "string(/Customers/Customer[@id=3]/Phone/text())", doc, XPathEvaluationResult.class); + verifyResult(result, "3333333333"); + } + + /* + * Test return type: Any::Nodeset. + */ + @Test(dataProvider = "document") + public void test14(XPath xpath, Document doc) throws XPathExpressionException { + XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer", doc); + verifyResult(result, "Customer"); + } + + /* + * Test return type: Any::Node. + */ + @Test(dataProvider = "document") + public void test15(XPath xpath, Document doc) throws XPathExpressionException { + XPathEvaluationResult<?> result = xpath.evaluateExpression("/Customers/Customer[@id=3]", doc); + verifyResult(result, "Customer"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathExpAnyTypeTest.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package javax.xml.xpath; + +import java.io.File; +import javax.xml.xpath.*; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/* + * @bug 8054196 + * @summary Test for the project XPath: support any type. This test covers the new + * evaluateExpression methods of XPathExpression. + */ +public class XPathExpAnyTypeTest extends XPathTestBase { + + /* + * Check that NPE is thrown when the class type is null. + */ + @Test(dataProvider = "xpath", expectedExceptions = NullPointerException.class) + public void test02(XPath xpath) throws XPathExpressionException { + XPathExpression exp = xpath.compile("1+1"); + double result = exp.evaluateExpression((Object)null, null); + } + + /* + * Parameter item can be null when the expression does not depends on the + * context. + */ + @Test(dataProvider = "xpath") + public void test03(XPath xpath) throws XPathExpressionException { + XPathExpression exp = xpath.compile("1+1"); + int result = exp.evaluateExpression((Object)null, Integer.class); + assertTrue(result == 2); + } + + /* + * Test return type: boolean. + */ + @Test(dataProvider = "document") + public void test04(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])"); + boolean result1 = exp.evaluateExpression(doc, Boolean.class); + assertTrue(result1); + } + + /* + * Test return type: numeric. + */ + @Test(dataProvider = "document") + public void test05(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("count(/Customers/Customer)"); + double result1 = exp.evaluateExpression(doc, Double.class); + assertTrue(result1 == 3.0); + + int result2 = exp.evaluateExpression(doc, Integer.class); + assertTrue(result2 == 3); + } + + /* + * Test return type: String. + */ + @Test(dataProvider = "document") + public void test06(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())"); + String result1 = exp.evaluateExpression(doc, String.class); + assertTrue(result1.equals("3333333333")); + } + + /* + * Test return type: NodeSet. + */ + @Test(dataProvider = "document") + public void test07(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("/Customers/Customer"); + XPathNodes nodes = exp.evaluateExpression(doc, XPathNodes.class); + assertTrue(nodes.size() == 3); + for (Node n : nodes) { + assertEquals(n.getLocalName(), "Customer"); + } + } + + /* + * Test return type: Node. + */ + @Test(dataProvider = "document") + public void test08(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]"); + Node n = exp.evaluateExpression(doc, Node.class); + assertEquals(n.getLocalName(), "Customer"); + } + + /* + * Test return type: Unsupported type. + */ + @Test(dataProvider = "document", expectedExceptions = IllegalArgumentException.class) + public void test09(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]"); + File n = exp.evaluateExpression(doc, File.class); + } + + /* + * Test return type: Any::Boolean. + */ + @Test(dataProvider = "document") + public void test10(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("boolean(/Customers/Customer[@id=3])"); + XPathEvaluationResult<?> result = exp.evaluateExpression(doc); + verifyResult(result, true); + } + + /* + * Test return type: Any::Number. + */ + @Test(dataProvider = "document") + public void test11(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("count(/Customers/Customer)"); + XPathEvaluationResult<?> result = exp.evaluateExpression(doc); + verifyResult(result, 3.0); + } + + /* + * Test return type: Any::String. + */ + @Test(dataProvider = "document") + public void test12(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("string(/Customers/Customer[@id=3]/Phone/text())"); + XPathEvaluationResult<?> result = exp.evaluateExpression(doc, XPathEvaluationResult.class); + verifyResult(result, "3333333333"); + } + + /* + * Test return type: Any::Nodeset. + */ + @Test(dataProvider = "document") + public void test13(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("/Customers/Customer"); + XPathEvaluationResult<?> result = exp.evaluateExpression(doc); + verifyResult(result, "Customer"); + } + + /* + * Test return type: Any::Node. + */ + @Test(dataProvider = "document") + public void test14(XPath xpath, Document doc) throws XPathExpressionException { + XPathExpression exp = xpath.compile("/Customers/Customer[@id=3]"); + XPathEvaluationResult<?> result = exp.evaluateExpression(doc); + verifyResult(result, "Customer"); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jaxp/test/javax/xml/jaxp/unittest/javax/xml/xpath/XPathTestBase.java Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package javax.xml.xpath; + +import java.io.ByteArrayInputStream; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; +import javax.xml.parsers.DocumentBuilderFactory; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; +import org.testng.annotations.DataProvider; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/* + * Base class for XPath test + */ +class XPathTestBase { + + static final String rawXML + = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" + + "<Customers>" + + " <Customer id=\"1\">" + + " <Name>name1</Name>" + + " <Phone>1111111111</Phone>" + + " <Email>123@xyz.com</Email>" + + " <Address>" + + " <Street>1111 111st ave</Street>" + + " <City>The City</City>" + + " <State>The State</State>" + + " </Address>" + + " </Customer>" + + " <Customer id=\"2\">" + + " <Name>name1</Name>" + + " <Phone>2222222222</Phone>" + + " <Email>123@xyz.com</Email>" + + " <Address>" + + " <Street>2222 222nd ave</Street>" + + " <City>The City</City>" + + " <State>The State</State>" + + " </Address>" + + " </Customer>" + + " <Customer id=\"3\">" + + " <Name>name1</Name>" + + " <Phone>3333333333</Phone>" + + " <Email>123@xyz.com</Email>" + + " <Address>" + + " <Street>3333 333rd ave</Street>" + + " <City>The City</City>" + + " <State>The State</State>" + + " </Address>" + + " </Customer>" + + "</Customers>"; + + void verifyResult(XPathEvaluationResult<?> result, Object expected) { + switch (result.type()) { + case BOOLEAN: + assertTrue(((Boolean) result.value()).equals(expected)); + return; + case NUMBER: + assertTrue(((Double) result.value()).equals(expected)); + return; + case STRING: + assertTrue(((String) result.value()).equals(expected)); + return; + case NODESET: + XPathNodes nodes = (XPathNodes) result.value(); + for (Node n : nodes) { + assertEquals(n.getLocalName(), expected); + } + return; + case NODE: + assertTrue(((Node) result.value()).getLocalName().equals(expected)); + return; + } + assertFalse(true, "Unsupported type"); + } + + /* + * DataProvider: XPath object + */ + @DataProvider(name = "xpath") + Object[][] getXPath() { + return new Object[][]{{XPathFactory.newInstance().newXPath()}}; + } + + /* + * DataProvider: Numeric types not supported + */ + @DataProvider(name = "invalidNumericTypes") + Object[][] getInvalidNumericTypes() { + XPath xpath = XPathFactory.newInstance().newXPath(); + return new Object[][]{{xpath, AtomicInteger.class}, + {xpath, AtomicInteger.class}, + {xpath, AtomicLong.class}, + {xpath, BigDecimal.class}, + {xpath, BigInteger.class}, + {xpath, Byte.class}, + {xpath, Float.class}, + {xpath, Short.class} + }; + } + + /* + * DataProvider: XPath and Document objects + */ + @DataProvider(name = "document") + Object[][] getDocument() throws Exception { + DocumentBuilderFactory dBF = DocumentBuilderFactory.newInstance(); + dBF.setValidating(false); + dBF.setNamespaceAware(true); + Document doc = dBF.newDocumentBuilder().parse( + new ByteArrayInputStream(rawXML.getBytes("UTF-8"))); + + return new Object[][]{{XPathFactory.newInstance().newXPath(), doc}}; + } +}
--- a/jaxws/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxws/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -293,3 +293,4 @@ e529374fbe526dbd668e5e98fc047b42b3bc6d33 jdk9-b45 64ca52b0bda8028636e4ccafbe1107befcdda47d jdk9-b46 6c17d648d03e4bf4729c3645f8db55d34115e0b7 jdk9-b47 +33e7e699804892c0496adf60ad67cc12855aeb61 jdk9-b48
--- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java Tue Feb 03 12:49:33 2015 +0100 +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/SchemaGenerator.java Wed Feb 04 18:22:46 2015 -0800 @@ -135,7 +135,7 @@ private void filterClass(List<Reference> classes, Collection<? extends Element> elements) { for (Element element : elements) { - if (element.getKind().equals(ElementKind.CLASS)) { + if (element.getKind().equals(ElementKind.CLASS) || element.getKind().equals(ElementKind.ENUM)) { classes.add(new Reference((TypeElement) element, processingEnv)); filterClass(classes, ElementFilter.typesIn(element.getEnclosedElements())); }
--- a/jdk/.hgtags Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/.hgtags Wed Feb 04 18:22:46 2015 -0800 @@ -290,3 +290,4 @@ 9acaa4f57b0b9e3757a7b4576ca9418a75ea8287 jdk9-b45 efedac7f44ed41cea2b1038138047271f55aacba jdk9-b46 b641c14730ac05d9ec8b4f66e6fca3dc21adb403 jdk9-b47 +ebb2eb7f1aec78eb6d8cc4c96f018afa11093cde jdk9-b48
--- a/jdk/make/Tools.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/Tools.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -34,28 +34,23 @@ 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 +################################################################################ + +$(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)) -$(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) - -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_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 @@ # 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)
--- a/jdk/make/data/checkdeps/refs.allowed Tue Feb 03 12:49:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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
--- a/jdk/make/gensrc/GensrcMisc.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/gensrc/GensrcMisc.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -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)
--- a/jdk/make/lib/CoreLibraries.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/lib/CoreLibraries.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -74,8 +74,6 @@ ########################################################################################## -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 @@ 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 @@ 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 @@ 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 @@ ########################################################################################## -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 @@ 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 + + LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\" 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) 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 @@ $(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 @@ $(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), 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)
--- a/jdk/make/lib/Lib-jdk.attach.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/lib/Lib-jdk.attach.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -31,7 +31,7 @@ $(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) \
--- a/jdk/make/lib/Lib-jdk.security.auth.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/lib/Lib-jdk.security.auth.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -28,9 +28,7 @@ ################################################################################ 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 @@ $(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 @@ 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" \
--- a/jdk/make/lib/NetworkingLibraries.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/lib/NetworkingLibraries.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -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), \
--- a/jdk/make/lib/NioLibraries.gmk Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/lib/NioLibraries.gmk Wed Feb 04 18:22:46 2015 -0800 @@ -65,7 +65,6 @@ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ SRC := $(BUILD_LIBNIO_SRC), \ EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \ - EXCLUDES := sctp, \ LANG := C, \ OPTIMIZATION := HIGH, \ CFLAGS := $(CFLAGS_JDKLIB) \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Tue Feb 03 12:49:33 2015 +0100 +++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Feb 04 18:22:46 2015 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -214,10 +214,10 @@ 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;
--- a/jdk/make/src/classes/build/tools/deps/CheckDeps.java Tue Feb 03 12:49:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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<String> 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<String,Set<String>> 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<JarEntry> 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<String> 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<String,Set<String>> 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 <image> <profile>"); - 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<Path> 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<Path> 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); - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/aix/native/libnet/aix_close.c Wed Feb 04 18:22:46 2015 -0800 @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2001, 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. + */ + +/* + * This file contains implementations of NET_... functions. The NET_.. functions are + * wrappers for common file- and socket functions plus provisions for non-blocking IO. + * + * (basically, the layers remember all file descriptors waiting for a particular fd; + * all threads waiting on a certain fd can be woken up by sending them a signal; this + * is done e.g. when the fd is closed.) + * + * This was originally copied from the linux_close.c implementation. + * + * Side Note: This coding needs initialization. Under Linux this is done + * automatically via __attribute((constructor)), on AIX this is done manually + * (see aix_close_init). + * + */ + +/* + AIX needs a workaround for I/O cancellation, see: + http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm + ... + The close subroutine is blocked until all subroutines which use the file + descriptor return to usr space. For example, when a thread is calling close + and another thread is calling select with the same file descriptor, the + close subroutine does not return until the select call returns. + ... +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/uio.h> +#include <unistd.h> +#include <errno.h> +#include <sys/poll.h> + +/* + * Stack allocated by thread when doing blocking operation + */ +typedef struct threadEntry { + pthread_t thr; /* this thread */ + struct threadEntry *next; /* next thread */ + int intr; /* interrupted */ +} threadEntry_t; + +/* + * Heap allocated during initialized - one entry per fd + */ +typedef struct { + pthread_mutex_t lock; /* fd lock */ + threadEntry_t *threads; /* threads blocked on fd */ +} fdEntry_t; + +/* + * Signal to unblock thread + */ +static int sigWakeup = (SIGRTMAX - 1); + +/* + * The fd table and the number of file descriptors + */ +static fdEntry_t *fdTable = NULL; +static int fdCount = 0; + +/* + * Null signal handler + */ +static void sig_wakeup(int sig) { +} + +/* + * Initialization routine (executed when library is loaded) + * Allocate fd tables and sets up signal handler. + * + * On AIX we don't have __attribute((constructor)) so we need to initialize + * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c') + */ +void aix_close_init() { + struct rlimit nbr_files; + sigset_t sigset; + struct sigaction sa; + + /* Check already initialized */ + if (fdCount > 0 && fdTable != NULL) { + return; + } + + /* + * Allocate table based on the maximum number of + * file descriptors. + */ + if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { + fprintf(stderr, "library initialization failed - " + "unable to get max # of allocated fds\n"); + abort(); + } + fdCount = nbr_files.rlim_max; + /* + * We have a conceptual problem here, when the number of files is + * unlimited. As a kind of workaround, we ensure the table is big + * enough for handle even a large number of files. Since SAP itself + * recommends a limit of 32000 files, we just use 64000 as 'infinity'. + */ + if (nbr_files.rlim_max == RLIM_INFINITY) { + fdCount = 64000; + } + fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); + if (fdTable == NULL) { + fprintf(stderr, "library initialization failed - " + "unable to allocate file descriptor table - out of memory"); + abort(); + } + + { + int i; + for (i=0; i < fdCount; i++) { + pthread_mutex_init(&fdTable[i].lock, NULL); + } + } + + /* + * Setup the signal handler + */ + sa.sa_handler = sig_wakeup; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(sigWakeup, &sa, NULL); + + sigemptyset(&sigset); + sigaddset(&sigset, sigWakeup); + sigprocmask(SIG_UNBLOCK, &sigset, NULL); +} + +/* + * Return the fd table for this fd or NULL is fd out + * of range. + */ +static inline fdEntry_t *getFdEntry(int fd) +{ + if (fd < 0 || fd >= fdCount) { + return NULL; + } + return &fdTable[fd]; +} + +/* + * Start a blocking operation :- + * Insert thread onto thread list for the fd. + */ +static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self) +{ + self->thr = pthread_self(); + self->intr = 0; + + pthread_mutex_lock(&(fdEntry->lock)); + { + self->next = fdEntry->threads; + fdEntry->threads = self; + } + pthread_mutex_unlock(&(fdEntry->lock)); +} + +/* + * End a blocking operation :- + * Remove thread from thread list for the fd + * If fd has been interrupted then set errno to EBADF + */ +static inline void endOp + (fdEntry_t *fdEntry, threadEntry_t *self) +{ + int orig_errno = errno; + pthread_mutex_lock(&(fdEntry->lock)); + { + threadEntry_t *curr, *prev=NULL; + curr = fdEntry->threads; + while (curr != NULL) { + if (curr == self) { + if (curr->intr) { + orig_errno = EBADF; + } + if (prev == NULL) { + fdEntry->threads = curr->next; + } else { + prev->next = curr->next; + } + break; + } + prev = curr; + curr = curr->next; + } + } + pthread_mutex_unlock(&(fdEntry->lock)); + errno = orig_errno; +} + +/* + * Close or dup2 a file descriptor ensuring that all threads blocked on + * the file descriptor are notified via a wakeup signal. + * + * fd1 < 0 => close(fd2) + * fd1 >= 0 => dup2(fd1, fd2) + * + * Returns -1 with errno set if operation fails. + */ +static int closefd(int fd1, int fd2) { + int rv, orig_errno; + fdEntry_t *fdEntry = getFdEntry(fd2); + if (fdEntry == NULL) { + errno = EBADF; + return -1; + } + + /* + * Lock the fd to hold-off additional I/O on this fd. + */ + pthread_mutex_lock(&(fdEntry->lock)); + + { + /* On fast machines we see that we enter dup2 before the + * accepting thread had a chance to get and process the signal. + * So in case we woke a thread up, give it some time to cope. + * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */ + int num_woken = 0; + + /* + * Send a wakeup signal to all threads blocked on this + * file descriptor. + */ + threadEntry_t *curr = fdEntry->threads; + while (curr != NULL) { + curr->intr = 1; + pthread_kill( curr->thr, sigWakeup ); + num_woken ++; + curr = curr->next; + } + + if (num_woken > 0) { + usleep(num_woken * 50); + } + + /* + * And close/dup the file descriptor + * (restart if interrupted by signal) + */ + do { + if (fd1 < 0) { + rv = close(fd2); + } else { + rv = dup2(fd1, fd2); + } + } while (rv == -1 && errno == EINTR); + } + + /* + * Unlock without destroying errno + */ + orig_errno = errno; + pthread_mutex_unlock(&(fdEntry->lock)); + errno = orig_errno; + + return rv; +} + +/* + * Wrapper for dup2 - same semantics as dup2 system call except + * that any threads blocked in an I/O system call on fd2 will be + * preempted and return -1/EBADF; + */ +int NET_Dup2(int fd, int fd2) { + if (fd < 0) { + errno = EBADF; + return -1; + } + return closefd(fd, fd2); +} + +/* + * Wrapper for close - same semantics as close system call + * except that any threads blocked in an I/O on fd will be + * preempted and the I/O system call will return -1/EBADF. + */ +int NET_SocketClose(int fd) { + return closefd(-1, fd); +} + +/************** Basic I/O operations here ***************/ + +/* + * Macro to perform a blocking IO operation. Restarts + * automatically if interrupted by signal (other than + * our wakeup signal) + */ +#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \ + int ret; \ + threadEntry_t self; \ + fdEntry_t *fdEntry = getFdEntry(FD); \ + if (fdEntry == NULL) { \ + errno = EBADF; \ + return -1; \ + } \ + do { \ + startOp(fdEntry, &self); \ + ret = FUNC; \ + endOp(fdEntry, &self); \ + } while (ret == -1 && errno == EINTR); \ + return ret; \ +} + +int NET_Read(int s, void* buf, size_t len) { + BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); +} + +int NET_ReadV(int s, const struct iovec * vector, int count) { + BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); +} + +int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, + struct sockaddr *from, int *fromlen) { + socklen_t socklen = *fromlen; + BLOCKING_IO_RETURN_INT( s, recvfrom(s, buf, len, flags, from, &socklen) ); + *fromlen = socklen; +} + +int NET_Send(int s, void *msg, int len, unsigned int flags) { + BLOCKING_IO_RETURN_INT( s, send(s, msg, len, flags) ); +} + +int NET_WriteV(int s, const struct iovec * vector, int count) { + BLOCKING_IO_RETURN_INT( s, writev(s, vector, count) ); +} + +int NET_SendTo(int s, const void *msg, int len, unsigned int + flags, const struct sockaddr *to, int tolen) { + BLOCKING_IO_RETURN_INT( s, sendto(s, msg, len, flags, to, tolen) ); +} + +int NET_Accept(int s, struct sockaddr *addr, int *addrlen) { + socklen_t socklen = *addrlen; + BLOCKING_IO_RETURN_INT( s, accept(s, addr, &socklen) ); + *addrlen = socklen; +} + +int NET_Connect(int s, struct sockaddr *addr, int addrlen) { + int crc = -1, prc = -1; + threadEntry_t self; + fdEntry_t* fdEntry = getFdEntry(s); + + if (fdEntry == NULL) { + errno = EBADF; + return -1; + } + + /* On AIX, when the system call connect() is interrupted, the connection + * is not aborted and it will be established asynchronously by the kernel. + * Hence, no need to restart connect() when EINTR is received + */ + startOp(fdEntry, &self); + crc = connect(s, addr, addrlen); + endOp(fdEntry, &self); + + if (crc == -1 && errno == EINTR) { + struct pollfd s_pollfd; + int sockopt_arg = 0; + socklen_t len; + + s_pollfd.fd = s; + s_pollfd.events = POLLOUT | POLLERR; + + /* poll the file descriptor */ + do { + startOp(fdEntry, &self); + prc = poll(&s_pollfd, 1, -1); + endOp(fdEntry, &self); + } while (prc == -1 && errno == EINTR); + + if (prc < 0) + return prc; + + len = sizeof(sockopt_arg); + + /* Check whether the connection has been established */ + if (getsockopt(s, SOL_SOCKET, SO_ERROR, &sockopt_arg, &len) == -1) + return -1; + + if (sockopt_arg != 0 ) { + errno = sockopt_arg; + return -1; + } + } else { + return crc; + } + + /* At this point, fd is connected. Set successful return code */ + return 0; +} + +int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) { + BLOCKING_IO_RETURN_INT( ufds[0].fd, poll(ufds, nfds, timeout) ); +} + +/* + * Wrapper for poll(s, timeout). + * Auto restarts with adjusted timeout if interrupted by + * signal other than our wakeup signal. + */ +int NET_Timeout(int s, long timeout) { + long prevtime = 0, newtime; + struct timeval t; + fdEntry_t *fdEntry = getFdEntry(s); + + /* + * Check that fd hasn't been closed. + */ + if (fdEntry == NULL) { + errno = EBADF; + return -1; + } + + /* + * Pick up current time as may need to adjust timeout + */ + if (timeout > 0) { + gettimeofday(&t, NULL); + prevtime = t.tv_sec * 1000 + t.tv_usec / 1000; + } + + for(;;) { + struct pollfd pfd; + int rv; + threadEntry_t self; + + /* + * Poll the fd. If interrupted by our wakeup signal + * errno will be set to EBADF. + */ + pfd.fd = s; + pfd.events = POLLIN | POLLERR; + + startOp(fdEntry, &self); + rv = poll(&pfd, 1, timeout); + endOp(fdEntry, &self); + + /* + * If interrupted then adjust timeout. If timeout + * has expired return 0 (indicating timeout expired). + */ + if (rv < 0 && errno == EINTR) { + if (timeout > 0) { + gettimeofday(&t, NULL); + newtime = t.tv_sec * 1000 + t.tv_usec / 1000; + timeout -= newtime - prevtime; + if (timeout <= 0) { + return 0; + } + prevtime = newtime; + } + } else { + return rv; + } + + } +}
--- a/jdk/src/java.base/aix/native/libnet/java/net/aix_close.c Tue Feb 03 12:49:33 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,491 +0,0 @@ -/* - * Copyright (c) 2001, 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. - */ - -/* - * This file contains implementations of NET_... functions. The NET_.. functions are - * wrappers for common file- and socket functions plus provisions for non-blocking IO. - * - * (basically, the layers remember all file descriptors waiting for a particular fd; - * all threads waiting on a certain fd can be woken up by sending them a signal; this - * is done e.g. when the fd is closed.) - * - * This was originally copied from the linux_close.c implementation. - * - * Side Note: This coding needs initialization. Under Linux this is done - * automatically via __attribute((constructor)), on AIX this is done manually - * (see aix_close_init). - * - */ - -/* - AIX needs a workaround for I/O cancellation, see: - http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.basetechref/doc/basetrf1/close.htm - ... - The close subroutine is blocked until all subroutines which use the file - descriptor return to usr space. For example, when a thread is calling close - and another thread is calling select with the same file descriptor, the - close subroutine does not return until the select call returns. - ... -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <pthread.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/uio.h> -#include <unistd.h> -#include <errno.h> -#include <sys/poll.h> - -/* - * Stack allocated by thread when doing blocking operation - */ -typedef struct threadEntry { - pthread_t thr; /* this thread */ - struct threadEntry *next; /* next thread */ - int intr; /* interrupted */ -} threadEntry_t; - -/* - * Heap allocated during initialized - one entry per fd - */ -typedef struct { - pthread_mutex_t lock; /* fd lock */ - threadEntry_t *threads; /* threads blocked on fd */ -} fdEntry_t; - -/* - * Signal to unblock thread - */ -static int sigWakeup = (SIGRTMAX - 1); - -/* - * The fd table and the number of file descriptors - */ -static fdEntry_t *fdTable = NULL; -static int fdCount = 0; - -/* - * Null signal handler - */ -static void sig_wakeup(int sig) { -} - -/* - * Initialization routine (executed when library is loaded) - * Allocate fd tables and sets up signal handler. - * - * On AIX we don't have __attribute((constructor)) so we need to initialize - * manually (from JNI_OnLoad() in 'src/share/native/java/net/net_util.c') - */ -void aix_close_init() { - struct rlimit nbr_files; - sigset_t sigset; - struct sigaction sa; - - /* Check already initialized */ - if (fdCount > 0 && fdTable != NULL) { - return; - } - - /* - * Allocate table based on the maximum number of - * file descriptors. - */ - if (-1 == getrlimit(RLIMIT_NOFILE, &nbr_files)) { - fprintf(stderr, "library initialization failed - " - "unable to get max # of allocated fds\n"); - abort(); - } - fdCount = nbr_files.rlim_max; - /* - * We have a conceptual problem here, when the number of files is - * unlimited. As a kind of workaround, we ensure the table is big - * enough for handle even a large number of files. Since SAP itself - * recommends a limit of 32000 files, we just use 64000 as 'infinity'. - */ - if (nbr_files.rlim_max == RLIM_INFINITY) { - fdCount = 64000; - } - fdTable = (fdEntry_t *)calloc(fdCount, sizeof(fdEntry_t)); - if (fdTable == NULL) { - fprintf(stderr, "library initialization failed - " - "unable to allocate file descriptor table - out of memory"); - abort(); - } - - { - int i; - for (i=0; i < fdCount; i++) { - pthread_mutex_init(&fdTable[i].lock, NULL); - } - } - - /* - * Setup the signal handler - */ - sa.sa_handler = sig_wakeup; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sigaction(sigWakeup, &sa, NULL); - - sigemptyset(&sigset); - sigaddset(&sigset, sigWakeup); - sigprocmask(SIG_UNBLOCK, &sigset, NULL); -} - -/* - * Return the fd table for this fd or NULL is fd out - * of range. - */ -static inline fdEntry_t *getFdEntry(int fd) -{ - if (fd < 0 || fd >= fdCount) { - return NULL; - } - return &fdTable[fd]; -} - -/* - * Start a blocking operation :- - * Insert thread onto thread list for the fd. - */ -static inline void startOp(fdEntry_t *fdEntry, threadEntry_t *self) -{ - self->thr = pthread_self(); - self->intr = 0; - - pthread_mutex_lock(&(fdEntry->lock)); - { - self->next = fdEntry->threads; - fdEntry->threads = self; - } - pthread_mutex_unlock(&(fdEntry->lock)); -} - -/* - * End a blocking operation :- - * Remove thread from thread list for the fd - * If fd has been interrupted then set errno to EBADF - */ -static inline void endOp - (fdEntry_t *fdEntry, threadEntry_t *self) -{ - int orig_errno = errno; - pthread_mutex_lock(&(fdEntry->lock)); - { - threadEntry_t *curr, *prev=NULL; - curr = fdEntry->threads; - while (curr != NULL) { - if (curr == self) { - if (curr->intr) { - orig_errno = EBADF; - } - if (prev == NULL) { - fdEntry->threads = curr->next; - } else { - prev->next = curr->next; - } - break; - } - prev = curr; - curr = curr->next; - } - } - pthread_mutex_unlock(&(fdEntry->lock)); - errno = orig_errno; -} - -/* - * Close or dup2 a file descriptor ensuring that all threads blocked on - * the file descriptor are notified via a wakeup signal. - * - * fd1 < 0 => close(fd2) - * fd1 >= 0 => dup2(fd1, fd2) - * - * Returns -1 with errno set if operation fails. - */ -static int closefd(int fd1, int fd2) { - int rv, orig_errno; - fdEntry_t *fdEntry = getFdEntry(fd2); - if (fdEntry == NULL) { - errno = EBADF; - return -1; - } - - /* - * Lock the fd to hold-off additional I/O on this fd. - */ - pthread_mutex_lock(&(fdEntry->lock)); - - { - /* On fast machines we see that we enter dup2 before the - * accepting thread had a chance to get and process the signal. - * So in case we woke a thread up, give it some time to cope. - * Also see https://bugs.openjdk.java.net/browse/JDK-8006395 */ - int num_woken = 0; - - /* - * Send a wakeup signal to all threads blocked on this - * file descriptor. - */ - threadEntry_t *curr = fdEntry->threads; - while (curr != NULL) { - curr->intr = 1; - pthread_kill( curr->thr, sigWakeup ); - num_woken ++; - curr = curr->next; - } - - if (num_woken > 0) { - usleep(num_woken * 50); - } - - /* - * And close/dup the file descriptor - * (restart if interrupted by signal) - */ - do { - if (fd1 < 0) { - rv = close(fd2); - } else { - rv = dup2(fd1, fd2); - } - } while (rv == -1 && errno == EINTR); - } - - /* - * Unlock without destroying errno - */ - orig_errno = errno; - pthread_mutex_unlock(&(fdEntry->lock)); - errno = orig_errno; - - return rv; -} - -/* - * Wrapper for dup2 - same semantics as dup2 system call except - * that any threads blocked in an I/O system call on fd2 will be - * preempted and return -1/EBADF; - */ -int NET_Dup2(int fd, int fd2) { - if (fd < 0) { - errno = EBADF; - return -1; - } - return closefd(fd, fd2); -} - -/* - * Wrapper for close - same semantics as close system call - * except that any threads blocked in an I/O on fd will be - * preempted and the I/O system call will return -1/EBADF. - */ -int NET_SocketClose(int fd) { - return closefd(-1, fd); -} - -/************** Basic I/O operations here ***************/ - -/* - * Macro to perform a blocking IO operation. Restarts - * automatically if interrupted by signal (other than - * our wakeup signal) - */ -#define BLOCKING_IO_RETURN_INT(FD, FUNC) { \ - int ret; \ - threadEntry_t self; \ - fdEntry_t *fdEntry = getFdEntry(FD); \ - if (fdEntry == NULL) { \ - errno = EBADF; \ - return -1; \ - } \ - do { \ - startOp(fdEntry, &self); \ - ret = FUNC; \ - endOp(fdEntry, &self); \ - } while (ret == -1 && errno == EINTR); \ - return ret; \ -} - -int NET_Read(int s